我们发布了绕口令计分服务,让老少皆宜的人都可以通过有趣的方式来争夺分数,提高流利度。
▼服务网址
https://hayakuchi-championship.com/
▼GitHub
https://github.com/tomo-kn/hayakuchi-championship
▼ 推特账号
https://twitter.com/tomokn5
* 由于使用的API,目前该服务PC 或 Android 设备上的 Chrome 浏览器只能在上面播放
介绍
你好!初出茅庐的工程师托莫我的名字是。
突然间,你对自己的流利程度和说话风格有信心了吗?
当我还是一个大学生的时候,我想提高我的歌唱能力,所以我参加了一个声乐训练班。口语课我去过
但是,月费仍然很高,很难继续下去。我一直觉得如果我能继续免费享受它会很好。
所以,”如果您可以创建一个可以以有趣的方式提高您的流利度和说话风格的网络应用程序,那么对它的需求不会很大吗?我决定创建这个服务。
服务概述和使用
1.首页
您可以从首页选择游戏模式或练习模式。
2.匹配页面
游戏开始后,将开始 60 秒倒计时。
题目依次随机给出,并根据发音准确度给予分数。
- 本垒打:2 分
- 命中:1 分
- 出局:0 分
此外,如果您连续击出 3 个本垒打,将在时间限制中增加 5 秒作为奖励。
当时间限制用完或出局重叠3次时,游戏结束。
3.练习页面
您可以练习游戏模式中给出的问题。
您可以在练习模式下播放录音,这样您就可以客观地分析您的发音。
| 练习页 | 结果页面 |
|---|---|
4.其他功能
如果您注册成为会员并登录,您可以看到我的页面。
您可以在我的页面上回顾过去的比赛结果和练习结果。
| 我的页面 |
|---|
此外,由于比赛模式中的最佳成绩显示在排名中,您可以享受与对手竞争的乐趣。
| 排行 |
|---|
请努力争取最高排名!
使用的技术
- 红宝石(3.1.2)
- Ruby on Rails (6.1.6)
- JavaScript
- jQuery
- AWS(ECS、ECR、Fargate、RDS、Route53、ALB、ACM、S3)
- 码头工人
- 圆CI
- R规范
- MySQL
使用的 API
- WebSpeechAPI(用于语音识别)
主要宝石
- 载波音频
- 雾-aws
- 引导程序
- jquery-rails
ER图
这一次,由于开发是基于 MVP(最小可行产品)的概念,所以在 ER 图中强调了简单性。
因此,ER图可能会根据未来的功能扩展而改变。
基础架构配置(架构)图
我们使用所有“AWS”、“Docker”和“CircleCI”来构建基础设施,这些都是现代基于 Web 的内部开发公司经常使用的。
发展期
6月初到8月初大约两个月,如果你花时间350-400 小时我认为这是关于
难点/改进点
我在基础设施方面做了很多努力。
这一次,我担心将开发机器从 Windows 10 更改为 Mac,但由于经济原因,我决定继续在 Windows 10 上进行开发。
所以我想,“如果你要在 Windows 10 上开发,Docker 是必不可少的,对吧?”Dockerをどうせ使うのなら、AWSもEC2じゃなくてECSを使って、CircleCIでCI/CDパイプラインを作って、かっこよく開発したい!
我决定实施它。
我有很多我需要的先验知识。Rails 教程完成后路线图在这里继续在街上学习,尤其是 Docker 在 Udemy 上评价很高变色龙的讲座我学会了使用
尽管做了所有的准备,但在开发过程中还有很多我们不知道的事情。一个错误需要 10 多个小时有时它被卡住并最终得到解决。
(特别是我在 Dockerfile 和 nginx.conf 上花了很多时间。)
Dockerfile,entrypoint.sh,nginx.conf的最终代码如下。
FROM ruby:3.1.2
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
# debconf: delaying package configuration, since apt-utils is not installedを非表示
# ENV DEBCONF_NOWARNINGS=yes
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
# yarnパッケージ管理ツールをインストール
RUN apt-get update && \
apt-get install -y build-essential \
curl apt-transport-https wget \
libpq-dev \
libgmp3-dev \
libsox-fmt-all sox libchromaprint-dev \
nginx \
sudo && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update -qq && apt-get install -y yarn nodejs mariadb-client && \
gem install bundler --update
RUN gem update --system
RUN yarn install --check-files
RUN bundle install
# nginx
RUN groupadd nginx
RUN useradd -g nginx nginx
ADD nginx/nginx.conf /etc/nginx/nginx.conf
COPY . /myapp
RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids
# コンテナ起動時に実行させるスクリプトを追加
EXPOSE 80
RUN chmod +x /myapp/entrypoint.sh
RUN chmod +x /myapp/bin/*
CMD [ "sh", "/myapp/entrypoint.sh" ]
#!/usr/bin/env bash
# アセットのプリコンパイル
bundle exec rails assets:precompile RAILS_ENV=production SECRET_KEY_BASE=placeholder
yarn cache clean
rm -rf node_modules tmp/cache
service nginx start
rm -f /myapp/tmp/pids/server.pid
cd /myapp
# DBの用意
bin/setup
bundle exec rake db:seed_fu
# sitemapの作成
bundle exec rake sitemap:refresh
# puma
bundle exec pumactl start
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log error;
pid /var/log/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
upstream myapp {
server unix:///myapp/tmp/sockets/puma.sock;
}
server {
listen 80;
server_name hayakuchi-championship.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
root /myapp/public;
location / {
try_files $uri @app;
}
location @app {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_pass http://myapp;
}
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
}
client_max_body_size 100m;
keepalive_timeout 5;
}
}
这一次,通过使用 ECS(Fargate)而不是 AWS 的 EC2,经常会出现错误,即使搜索也没有得到很好的信息。
很多英文资料都挺难的,不过谢谢尽管我没有经验,但我能够积累有关基础设施的知识所以我很高兴我没有放弃并努力工作。
完成了用户可以享受的评分功能
这项服务是否受欢迎是“游戏模式有多好玩?我认为这取决于
因此,匹配模式的得分功能是在调整后调整的。
我会提取一些。
// 採点
function gradeText() {
const accuracy = seido.innerHTML;
const resultWord = kotoba.innerHTML.replace(/\s+/g, "");
const sentenceWord = odai.innerHTML.replace(/\s+/g, "");
trace("精度: " + accuracy);
trace("あなたの言葉は、" + resultWord + "と聞こえました");
// confidenceの威力を約7分の5にする
const accuracyFixed = Number(accuracy) + ((1 - Number(accuracy)) / 3.5);
trace("修正した精度: " + accuracyFixed);
const scoreOriginal = Math.round((100 - levenshteinDistance(resultWord, sentenceWord)) * accuracyFixed * 10) / 10;
trace("scoreOriginal: " + scoreOriginal);
// misconversionの処理
var scoreMisconversion = 0;
if(gohenkan.innerHTML != "なし"){
var sentenceMisconversionArray = gohenkan.innerHTML.split(',');
var scoreMisconversionAll = [];
for (let i = 1; i < sentenceMisconversionArray.length; i++) {
var sentenceMisconversionWord = sentenceMisconversionArray[i].replace(/\s+/g, "");
trace("誤変換ワード: " + sentenceMisconversionWord);
scoreMisconversionAll.push(Math.round((100 - levenshteinDistance(resultWord, sentenceMisconversionWord)) * accuracyFixed * 10) / 10);
}
trace("scoreMisconversionAll: " + scoreMisconversionAll);
var scoreMisconversion = Math.max(...scoreMisconversionAll);
trace("scoreMisconversion: " + scoreMisconversion);
};
const score = Math.max(scoreOriginal, scoreMisconversion);
trace("スコアは、" + score + "点です。");
// 95点以上はホームラン、90点以上はヒット、90点未満はアウト
if(score >= 95){
trace("ホームラン!");
gameScore += 2;
homerunCount += 1;
scoreTemporary.innerHTML = "Score: " + gameScore;
batterImage.src = 'hayakuchi-championship-batter3.png';
if(homerunCount <= 2){
homerunSound.play();
}
} else if(score >= 90) {
trace("ヒット");
gameScore += 1;
homerunCount = 0;
scoreTemporary.innerHTML = "Score: " + gameScore;
batterImage.src = 'hayakuchi-championship-batter2.png';
hitSound.play();
} else {
trace("アウト…");
outScore += 1;
homerunCount = 0;
if(outScore == 1){
outTemporary.innerHTML = " Out: " + "<span style='color:red'>●</span>";
outSound.play();
} else if(outScore == 2){
outTemporary.innerHTML = " Out: " + "<span style='color:red'>●●</span>";
outSound.play();
}
batterImage.src = 'hayakuchi-championship-batter4.png';
};
// 3回連続ホームランの場合、残り時間に5秒追加のボーナス
if(homerunCount == 3) {
trace("3回連続ホームランボーナス!残り時間5秒追加!");
homerunCount = 0;
originTime += 5;
homerunsSound.play();
jsAnimation.classList.add('is-show');
setTimeout(() => {
jsAnimation.classList.remove('is-show');
}, 2000)
};
// ゲームが続行中の場合、以下の処理を行う
if(gameContinue) {
// アウトが3回重なったらゲームセット関数を呼び出す
if(outScore == 3) {
gameSet();
} else {
// 次のお題を選び録音ボタンを裏側で押す
selectSentence();
rec.click();
};
};
};
//中略
// レーベンシュタイン距離の定義
function levenshteinDistance( str1, str2 ) {
var x = str1.length;
var y = str2.length;
var d = [];
for( var i = 0; i <= x; i++ ) {
d[i] = [];
d[i][0] = i;
}
for( var i = 0; i <= y; i++ ) {
d[0][i] = i;
}
var cost = 0;
for( var i = 1; i <= x; i++ ) {
for( var j = 1; j <= y; j++ ) {
cost = str1[i - 1] == str2[j - 1] ? 0 : 1;
d[i][j] = Math.min( d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost );
}
}
return d[x][y];
};
为了让您了解评分功能,
- 根据Levenshtein距离扣分
- 使用WebSpeechAPI置信度,按准确度扣分
- 如果出现不合理的误译,请提前注册误译列表,并使用该误译列表进行评分
这就是它的工作原理。
我希望通过尽可能减少不合理并引入增强游戏性的评分功能来让更多的人享受游戏。
综上所述
这是我第一次创建一个合适的网络应用程序,但它很有趣,我比以前更喜欢编程。
我想继续致力于它。
如果你觉得“很有趣”和“我想支持你”,请LGTM 或股票或使用本文或此服务分享到推特如果你能做到,我将不胜感激。
另外,我们计划尽可能地改进这项服务,所以如果您在玩完后有任何意见或要求,例如“我想要这种功能”,请告诉我。评论或私信请告诉我们!
感谢您一直阅读到最后!
▼服务网址
https://hayakuchi-championship.com/
▼GitHub
https://github.com/tomo-kn/hayakuchi-championship
▼ 推特账号
https://twitter.com/tomokn5
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308623015.html