ストリーム 3 プロジェクト: データ中心開発 - コード研究所。
このプロジェクトは Flask Microframework を使用して構築されており、水泳や陸上競技で複数のアスリートの時間を計測するための手動ストップウォッチとして使用できます。このアプリケーションの目的は、文書で記録しておくのではなく、タイムを個別に計測する人数を減らし、タイムを直接保存することで、スポーツのタイム計測の効率を向上させることです。
このアプリケーションは教育目的のみを目的としています。このアプリケーションは商用目的ではありません。
このプロジェクトのライブデモはここにあります。このアプリは Heroku でホストされています。時刻は MongoDB に保存されます。
このタイミング アシスタント アプリのアイデアは、幼少期に水泳に親しんだことから生まれました。さまざまな理由により、プール内のタッチパッドが必ずしも正確な時刻や判読可能な時刻を生成するとは限らないため、計時プロセスには多くの人が関与する必要があることに気づきました。さらに、コーチと選手は、デッキ上で各レーンのタイムを計る複数の人がクリップボードにタイムを記録しない限り、大会が終了するまで最終タイムやスプリットを見ることができません。
私はこの機会に、計測プロセスに関わる人数を削減するアプリケーションを作成する機会があると考え、競技会の効率を高め、選手やコーチへのフィードバックを向上させたいと考えました。このアプリケーションは、あらゆるタイムスポーツ向けに最適化でき、このバージョンは水泳と陸上競技の両方で動作します。
コーチもタイマーも同様に、スポーツ、大会、イベント、ヒート、レーン番号を選択でき、大会で何が起こっているかを把握するのに役立ちます。また、タイムを保存して「タイムを表示」をクリックするとタイムが表示されるため、レース後にアスリートに即座にフィードバックを提供することもできます。また、一度に 1 つのイベントだけではなく、大会の累積結果を確認できるようにしたいとも思いました。
このデザインにはテーマは使用されていません。ページ上に多くのタイマーとデータがあると、乱雑で整理されていないように見える可能性があるため、モダンなデザインが選択されました。私はこれを望んでいなかったので、タイマー、時間、イベントのオプションを 1 ページにまとめたいと考えていましたが、ページを縦に 3 つに分割し、各 3 分の 1 に顕著な違いを生むことが最善の方法であると考えました。
Timing Assistant は、Python の Flask Microframework を使用して構築され、バックエンドには NoSQL (MongoDB) データベース、フロントエンドには HTML、CSS、JavaScript、jQuery が使用され、ストップウォッチ機能は AJAX でバックエンドに接続されました。
アプリのホームページで、ユーザーはタイムを計測したいスポーツ、チーム名、ユーザー名、大会名を入力します。このアクションにより、ストップウォッチ ページが表示され、そこで時間を計測したいイベントとヒートを選択できます。ユーザーは最大 3 つのレーンの時間を計測し、3 つのレーンすべてで分割を行うことができます。 3 つの小さなタイマーは個別に設定されているため、すべてを停止した後、ユーザーはメイン タイマーを手動で停止する必要があります。ただし、これは、コーチがレースの所要時間を知り、水泳選手のタイムと最終完走者のタイムを比較したい場合に特に便利です。メインタイマーの時間はデータベースに保存されません。
「送信」をクリックすると、イベントとヒートが表示されます。その後、メイン ストップウォッチの「START」を押して、最大 3 つのレーンの計時を開始できます。これにより 4 つのストップウォッチがすべて開始されますが、データベースに保存されるのは下の 3 つだけです。 「SPLIT」ボタンを使用して、各レーンのスプリットタイムを個別に収集するオプションがあります。各タイマーは個別に停止および開始でき、メイン タイマーがすべてのストップウォッチ (開始、停止、リセット) を制御します。
「SAVE TIMES」をクリックすると、Javascript ファイル内の AJAX 呼び出しを使用して時間が保存され、Flask が MongoDB に接続された状態で時間が Flask にプッシュされます。時間を保存したら、「VIEW TIMES」をクリックすると、ストップウォッチの下に時間が表示されます。
イベントやヒートを指定せずにデータも保存されます (タイムを表示する場合、これらのフィールドは空白になります)。これは、コーチが試合ではなく練習でストップウォッチを使用したい場合に便利です。
コーチがデータを PDF またはその他のファイル形式でダウンロードできるようにしたいと考えています。長期的には、手書きのデータに頼ったり、昔の大会に戻って見たいときに毎回このサイトに頼ったりする必要がなく、記録のタイミングをすべて手動で維持できるようになります。
また、コーチが各ヒートのアスリートの数に基づいて、表示するストップウォッチの数を選択できるようにしたいと考えています。現在、一度に計測できるのは 3 人のアスリートのみであり、3 人未満の選手の計測を選択することはできません。
また、試合や練習のタイミングをより細かく設定できる「練習モード」や「試合モード」も実装したいと考えています。ミートモードでは、イベントまたはヒートの選択にさらに多くの制限が設けられ、コーチがタイムを計りたいレーンの数を選択できるようになります。練習モードでは、コーチはイベントやヒートを指定する必要がなく、(特定のドリルなどの)記録時間をメモすることができます。
このプロジェクトのテストはすべて手動で行われました。ランディング ページのフォームには、ユーザーがフォームのフィールドに入力しないことを防ぐために入力タグに必須属性があります。これは、Flask アプリのルートがこれらの入力に依存しているため、400 エラーが発生するためです。
Ajax 機能と [時間の保存] ボタンはコンソール経由でテストされ、データが MongoDB で正しくフォーマットされていることを確認しました。タイマーから収集されたデータと意図されたデータ構造もテストされました。
レーンごとに 1 つのドキュメントを使用して個別に時間を節約:
同じドキュメント内に表示されるレーンの時間 (注: テスト目的で、同じドキュメント内に 2 つのレーンが確実に表示されるように、ここでは 2 つのレーンのみが保存されています。):
正しいデータ構造:
ストップウォッチのテストも手動で行われ、メインのリセット ボタンがストップウォッチをリセットしてすべてのタイマーからスプリットをクリアするのに対し、個々のストップウォッチは自分の時間とスプリットのみをクリアすることを確認しました。さらに、メインのストップウォッチがすべてのストップウォッチを制御するのに対し、個々のストップウォッチは独自のスタート/ストップ機能のみを制御する必要があるため、これはスタート/ストップ機能についてもテストされました。
すべての Flask パスもテストされ、すべてのリンクが機能し、入力内の珍しい値を処理できること、および HTML ファイル内の Jinja 経由で入力が適切に表示されることを確認しました。
テストの過程で、2 人のユーザーが同じ大会名または同じクラブ名を持つ可能性があり、その結果、ユーザーが他の人のデータに遭遇する可能性があることに気付きました。そのため、テンプレートで時間を表示するには、対応する時間を表示するためにランディング ページの 3 つの入力フィールドが一致する必要があることを確認するために、次のコードを含めました。これには、時間の相互保存や相互表示を防ぐために、正しいチーム名、ユーザー名、および大会名が一致する必要があります。
{% if time.team == team %}
{% if time.username == username %}
{% if time.meet == meets %}
各レーンの分割は当初、次の形式で表示されていました。
split: ["00:02.2300:01.45"]
ただし、次のようにリストに表示したいと考えていました。
split: ["00:02.23", "00:01.45"]
そのため、この文字列を 9 文字ごとにリスト内の複数の文字列に分割するリスト内包表記 (レーンに対して複数の分割が行われた場合) を実装する必要がありました。
HTML timer_page.html では、AJAX 関数のデータを送信しているフォームに終了タグが含まれているように見えますが、時間を MongoDB に保存するには、最終時間、スプリット、レーン データをすべて含める必要があります。 。スタイルやその他の要素を表示する必要があるため、フォームが他の要素と順序が異なっているように見えます。また、HTML を見ると空のタグがありますが、これは jQuery を使用して HTML に分割時間が挿入されている場所です。
タイムを保存するときに、各タイマーに同じレーン (たとえば、レーン 1) を選択すると、レーン 1 のタイムのうち 1 つだけが表示タイムに表示されます。ただし、データ構造の性質上、レーンを選択しないと保存したタイムを表示できないため、レーンを選択する必要があります。ユーザーがレーンを指定しない場合に備えて、レーン ドロップダウンはデフォルトでレーン 1、ランド 2、ランド 3 に保存されるように設定されています。ユーザーがヒート中の 2 つのレーンで同じレーン番号を選択した場合、タイムの保存を禁止する検証を実装したいと考えています。
ストップウォッチを実行する Javascript 関数は、このアプリケーション用の Sara のストップウォッチ チュートリアルのコーディングから変更されています。一部の HTML も彼女の例をモデルにしていますが、スタイル、複数のボタン、分割、レーンに合わせて変更されています。
JavaScript では、ページを更新する代わりにすべてのストップウォッチをリセットするようにリセット ボタンのリセット関数が変更されました。また、このプロジェクトの UX には不要な機能であるため、小さなストップウォッチごとに個別のリセット ボタンが削除されました。スプリット機能も追加されました。 jQuery を使用したボタンのスタイル変更のために、Start/Stop 関数が変更されました。 UX 用にメインのストップウォッチが追加されたため、コーチは水泳のスコアボードと同様に、個々のタイムとともに合計経過時間を確認できるようになりました。 Ajax を使用して値を Flask と MongoDB に渡すための保存ボタンが追加されました。
Ajax 関数は、Stack Overflow からのこの投稿に基づいてモデル化され、他の Ajax の使用法と構文のパターンを確認することで、このプロジェクトに適合するように修正されました。 AJAX 呼び出しが行われたときにページがリロードされないように、preventDefault が追加されました。
Jinja の再帰を使用して、Python でネストされた辞書を反復処理し、すべてのレーンがループして表示されるようにすることで時間をレンダリングし、データを適切に満たしました。 Stack Overflow のこのメソッドはガイドラインとして従っており、データ構造の性質に合わせて変更されました。
ストップウォッチの JavaScript 関数は、選択したレーンの数に基づいてユーザーが画面に表示するストップウォッチの数を決定できるようにリファクタリングが試みられました。
var stopwatches = [ ] ;
var i ;
for ( i = 0 ; i <= 1 ; i ++ ) {
var stopwatch = new timing ( "timerLabel" + i , "start" + i , "splitLabel" + i ) ;
stopwatches . push ( stopwatch ) ;
console . log ( i ) ;
document . getElementById ( "start" + i ) . onclick = function ( ) {
stopwatches [ i ] . start ( ) ;
}
document . getElementById ( "reset" + i ) . onclick = function ( ) {
stopwatches [ i ] . reset ( ) ;
}
document . getElementById ( "split" + i ) . onclick = function ( ) {
stopwatches [ i ] . split ( ) ;
}
console . log ( stopwatches ) ;
}
このように for ループでこれらを記述しようとすると、stopwatches[i].start() はi
変更可能な変数として読み取れませんが、ハードコードされている場合には問題はありませんでした。
document . getElementById ( "reset" + i ) . onclick = function ( ) {
stopwatches [ 0 ] . reset ( ) ;
}
document . getElementById ( "split" + i ) . onclick = function ( ) {
stopwatches [ 0 ] . split ( ) ;
}
私は、対応するストップウォッチを表示させるための if ステートメントを使用する、別の方法でアプローチしようとしました。
上記の for ループから取得した引数としてi
を関数に渡そうとしましたが、失敗しました。
function chooseNumberOfStopwatches ( i ) {
if ( i == 1 ) {
stopwatches_one . start ( ) ;
}
else if ( i == 2 ) {
stopwatches_one . start ( ) ;
stopwatches_two . start ( ) ;
} else {
console . log ( 'else' ) ;
}
}
このリポジトリのクローンを作成することに興味がある場合は、requirements.txt 内のすべてをセットアップしてインストールするには、ターミナルで次のコマンドを実行します。
$ sudo pip3 -r install requirements.txt
このプロジェクトでは Cloud9 を使用したため、別のエディターを使用している場合はターミナル コマンドが異なる可能性があることに注意してください。エディター固有のターミナル コマンドの詳細については、使用しているエディターのドキュメントを参照してください。 MongoDB のすべての秘密キーは隠されており、私に固有のものであるため、個別に取得する必要があります。