| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | ||||||||||||||||||||||||||
2 | 科 目 名 | 講 座 名 | 年度/時期 | 授業形態 | ||||||||||||||||||||||
3 | Androidアプリ演習 | Androidアプリ演習 | 講義 | |||||||||||||||||||||||
4 | 授業時間 | 回数 | 単位数(時間数) | 必須・選択 | 担当教員 | |||||||||||||||||||||
5 | 90分 | 30回 | 2単位(45時間) | |||||||||||||||||||||||
6 | 科目のねらい | |||||||||||||||||||||||||
7 | Androidは世界で広く利用されているスマートフォン向けOSであり、品質が高く安定したAndroidアプリを効率よく開発できる技術者が求められている。 本科目では、KotlinおよびJetpack Composeを用いたAndroidネイティブアプリ開発の実習を通じて、宣言型UIを中心とした開発手法を理解し、状態管理や画面構築などの実装に落とし込むことで、実践的なアプリ開発力を身につける。 | |||||||||||||||||||||||||
8 | 授 業 の 概 要 | |||||||||||||||||||||||||
9 | 統合開発環境Android Studioを用い、プログラミング言語KotlinとJetpack ComposeによるAndroidネイティブアプリ開発の技術と知識を、演習を通じて習得する。具体的には、Jetpack Composeによる宣言型UIの設計と実装、状態管理、イベント処理、画面遷移、データの保存と取得など、アプリ開発に必要となる要素を段階的に学ぶ。学習した内容を題材アプリの制作に適用し、動作確認と改善を繰り返しながら、保守しやすく品質の高いアプリを効率よく開発する力を身につける。 | |||||||||||||||||||||||||
10 | 授業終了時の到達目標 | |||||||||||||||||||||||||
11 | KotlinとJetpack Composeを用い、次の技術要素を含む基本的なAndroidネイティブアプリの開発。 ・Jetpack ComposeによるUIレイアウト設計、画像や音声などのメディア素材の活用 ・宣言型UIによるユーザーインターフェースの構築、状態管理、画面遷移処理 ・ローカルデータの保存と取得、ネットワーク通信によるデータ取得 ・通信エラーを考慮した処理、Activityなどのライフサイクルを踏まえた処理の実装 | |||||||||||||||||||||||||
12 | # | 授業概要 | 詳細 | 書籍対応セクション | 授業お役立ちメモ | |||||||||||||||||||||
13 | 1 | 授業説明および、Androidアプリの開発準備(Chapter1)#1 | 授業説明:科目の狙い、到達目標、講義計画の説明。Android Studioの役割と開発環境の全体像の確認。 演習:開発環境の構築。Android Studioの初期設定、新規プロジェクトの作成、エミュレータの起動と動作確認。 | 1.3 Android Studioをセットアップする 1.4 新規プロジェクトを作成する | オンラインインストールをすると、ネットワークがパンクする恐れがあります。また、時間もかかるので、セットアップネタをUSBで配布すr方法をお勧めします。シート「事前準備」「学生の作業」を参照 | |||||||||||||||||||||
14 | 2 | Androidアプリの開発準備(Chapter1)#2 | Android Studio初期設定の継続を行う。 Androidエミュレータの作成および設定を行い、アプリを実行して動作確認を行う。 Compose Previewの操作を確認し、リソースの導入とアプリアイコンの変更を実施する。あわせて、プロジェクトの終了と再開など基本的な操作手順を習得する。 | 1.5 Hello Android!を画面に表示する | セットアップすると、最新版のエミュレータがセットアップされています。これを使うならそれでもOKです。 変更する場合、SDKのダウンロードが動作します。インストーラほどではないですが、1GB程度のダウンロードになります。 | |||||||||||||||||||||
15 | 3 | メッセージ表示アプリの作成(Chapter2) #1 | メッセージ表示アプリの作成を通じて、プロジェクト作成、実行、修正反映といったAndroid Studioの基本操作に慣れる。 | 2.5 開発を進めよう ・Step 1 新規プロジェクトを作成する ・Step 2 アプリを実行する ・Step 3 表示するメッセージを変更する | ||||||||||||||||||||||
16 | 4 | メッセージ表示アプリの作成(Chapter2) #2 | アプリ制作を通じてAndroid Studioの基本操作に慣れる。 ボタン追加とクリック処理の実装を題材に、Jetpack Composeの基本的な記法とイベント処理を学ぶ。 Kotlin Playgroundの利用方法を確認し、変数宣言と文字列操作を中心としたKotlinの基本文法を課題演習を通じて定着させる。 | 2.5 開発を進めよう ・Step 4 ボタンを追加する ・Step 5 もう1つボタンを追加する 2.7 Kotlinの学習方法について ・kotlin playgroundの使い方を説明 2.8 復習:Kotlinの理解度を高めよう ・課題1 文字列の結合について理解度を高める ・課題2 変数宣言と型について理解度を高める ・課題3 変数宣言と型(型推論)について理解度を高める | ■時間が余る場合 ・ボタンを追加。「こんにちは」の表示 ・ボタンを追加。「挨拶」時間帯によって、挨拶方法を変更する | |||||||||||||||||||||
17 | 5 | High&Lowゲームの作成(Chapter3) #1 | Jetpack Composeによる宣言型UIの基本を学ぶ。 ゲームアプリの制作を題材に、状態変数を用いた表示更新の考え方を理解し、処理結果に応じてボタン表示を切り替えるなど状態に基づくUI制御を実装する。 あわせて、アプリ構成の検討からプロジェクト作成、ゲームロジック実装までの基本的な開発手順を確認する。 | 3.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 ゲームロジックを実装する ・Step 4 ボタンの表示を制御する | ||||||||||||||||||||||
18 | 6 | High&Lowゲームの作成(Chapter3) #2 | Jetpack Composeによる宣言型UIの基本を学ぶ。 Modifierを用いたUI配置と、装飾による見た目の調整を実践し、数字表示をカード風に整えるなど、画面レイアウトの設計と実装を行う。 あわせて、Kotlinの関数、ラムダ式、高階関数について、課題演習を通じて理解を深める。 | 3.5 開発を進めよう ・Step 5 数字をカード風に表示する ・Step 6 レイアウトを整える 3.7 復習:Kotlinの理解度を高めよう ・課題1 変数宣言の仕方について理解度を高める ・課題2 関数とラムダ式について理解度を高める ・課題3 高階関数について理解度を高める | ■時間が余る場合 ・カードの??を、赤など塗り、トランプ風に ・トランプ画像を取り込んでみる (画像はネット検索や生成AIで作る) | |||||||||||||||||||||
19 | 7 | サイコロアプリの作成(Chapter4) #1 | Kotlinにおける乱数の扱いを学び、サイコロの目を決定するロジックとして実装する。 あわせて、Androidアプリで画像リソースを扱う手順を理解し、Jetpack Composeで画像を用いたUI表示を実装する。 アプリ構成の検討からプロジェクト作成までの基本手順を確認し、ロジックと画面表示を結び付ける実装の流れを習得する。 | 4.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 サイコロの目を決めるロジックを実装する ・Step 4 画像を使ってサイコロを表示する | ||||||||||||||||||||||
20 | 8 | サイコロアプリの作成(Chapter4) #2 | Jetpack Composeのレイアウト機能を用いて複数の画像を配置し、ModifierによるUIの装飾と調整を通じて画面の見た目を整える。 サイコロを転がす演出を題材に、状態変数の更新とコルーチンを用いた時間差処理を組み合わせ、簡易アニメーションの実装を通じて非同期処理の基本を学ぶ。 あわせて、論理演算子、if式、Listに関するKotlinの基礎事項を課題演習を通じて定着させる。 | 4.5 開発を進めよう ・Step 5 サイコロを3個に増やす1 ・Step 6 サイコロを転がす(簡易アニメーションを追加する) 4.7 復習:Kotlinの理解度を高めよう ・課題1 論理演算子の理解度を高める ・課題2 if式の理解度を高める ・課題3 Listの理解度を高める1 ・課題4 Listの理解度を高める2 | ■時間が余る場合(Chap4メモシートを参照) ・サイコロを左から順に止まる処理の追加 ・チンチロリンのロジックを追加する | |||||||||||||||||||||
21 | 9 | 鍵盤アプリ(Chapter5) #1 | Jetpack Composeのレイアウト機能を応用し、鍵盤アプリのUI構築を通じて複数要素の配置と構成の考え方を学ぶ。 白鍵盤の実装を題材に、状態変数とListを組み合わせた表示制御を行い、リソース管理を含む実装の流れを理解する。 あわせて、音声リソースの利用方法を学び、音声再生処理を組み込んだアプリ開発手順を習得する。 | 5.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 音声を再生する ・Step 4 白鍵盤を実装する | ||||||||||||||||||||||
22 | 10 | 鍵盤アプリ(Chapter5) #2 | Jetpack Composeのレイアウト機能を応用し、黒鍵盤を重ねて配置するなど複雑なUI構築手法を学ぶ。 UIの部品化を題材にComposable関数を自作し、再利用しやすい構成に整理する設計手法を習得する。 あわせて、状態変数とListを組み合わせた表示制御を継続し、音声リソースを利用した再生処理を含む実装の流れを理解する。 | 5.5 開発を進めよう ・Step 5 UIを部品化する ・Step 6 黒鍵盤を実装する | ||||||||||||||||||||||
23 | 11 | 鍵盤アプリ(Chapter5) #3 | 音声再生処理を題材に、音声リソースの扱い方を発展させ、より適切な再生方法やリソース管理の考え方を学ぶ。 あわせて、Kotlinにおける例外処理、繰り返し処理、null許容型の扱いについて、課題演習を通じて理解を深める。 List操作(forループ、map)を復習し、データの変換と処理の流れを整理する。 | 5.5 開発を進めよう Step 7 音声再生方法を改善する(任意) 5.7 復習:Kotlinの理解度を高めよう ・課題1 try-finallyの復習 ・課題2 null許容型とletの理解度を高める ・課題3 リストとforループの復習1 ・課題4 リストとforループの復習2 ・課題5 リストとmapの理解度を高める | ■時間が余る場合 ・鍵盤を押したときに、バイブレーションでフィードバック →実機じゃないと確認ができない ■時間が足りない場合 ・Step 7をスキップする(なくても成り立つので) | |||||||||||||||||||||
24 | 12 | タイマーアプリ(Chapter6) #1 | 標準的な画面レイアウトを題材に、完成イメージから必要な画面要素と作業内容を整理し、開発の全体像を把握する。 Jetpack Composeを用いたUI構築を実践し、操作ボタンを配置して動作の流れを確認する。 ViewModelによる状態管理の基本を学び、UIと処理を分離した構成で実装を進める。 | 6.1 完成したアプリをイメージしよう 画面の完成イメージから、作業内容及び全体像を把握する 6.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 画面作成の準備をする ・Step 4 ボタン押下で動作のイメージを確認する | ||||||||||||||||||||||
25 | 13 | タイマーアプリ(Chapter6) #2 | ViewModelによる状態管理を前提に、タイマーの基本機能を実装し、状態変化に応じてUIを更新する方法を学ぶ。 あわせて、コルーチンを用いた時間処理を実装し、タイマー終了時のメッセージ表示と通知音の再生を通じて、非同期処理とイベント通知の扱いを習得する。 | 6.5 開発を進めよう ・Step 5 タイマーの基本機能を実装する ・Step 6 タイマーの終了をメッセージと音で通知する | ||||||||||||||||||||||
26 | 14 | タイマーアプリ(Chapter6) #3 | ViewModelによる状態管理を継続し、時間の増減操作を実装することで、ユーザー操作に応じた状態更新とUI反映の流れを定着させる。 DataStoreを用いて設定値の保存と復元を実装し、アプリ再起動後も設定を保持するための永続化手法を学ぶ。 | 6.5 開発を進めよう ・Step 7 時間の増減を実装する ・Step 8 設定値の保存・復元を実装する | ■時間が足りない場合 #15にて続きを実装する | |||||||||||||||||||||
27 | 15 | タイマーアプリ(Chapter6) #4 | タイマーアプリ全体を振り返り、ViewModelによる状態管理とScaffoldを用いた画面構成について復習する。 Kotlinのスコープ関数と安全なnullの扱い方について、課題演習を通じて理解を深める。 | 6.5 開発を進めよう ・全体的な振り返りやおさらいをする。特にViewModeの機能は重要 6.7 復習:Kotlinの理解度を高めよう ・課題1 スコープ関数の利用方法について理解度を高める ・課題2 安全なnullの扱い方について理解度を高める | ■時間が余る場合 ・ダイアログなどを用いて、複数件設定を保存する機能を作る (1)上限5件。保存ボタンを押すたびに追加 (2)復元ボタンを押すとダイアログを表示する。リスト表示。タップで、指定の時間に設定を変更する | |||||||||||||||||||||
28 | 16 | ToDoアプリ(Chapter7) #1 | リスト形式の画面を題材に、Scaffoldを用いた画面構成と、TopAppBarなどの基本要素を含むレイアウト設計を学ぶ。 ダミーデータを用いてToDo一覧を表示し、LazyColumnによる一覧表示の実装手順と、データと画面を結び付ける流れを理解する。 完成イメージから必要な画面要素と作業内容を整理し、以降の実装に向けた全体像を把握する。 | 7.1 完成したアプリをイメージしよう 画面のイメージを見ながら、全体的な作業内容を想像する 7.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 画面作成の準備をする ・Step 4 ToDo一覧を表示する | ||||||||||||||||||||||
29 | 17 | ToDoアプリ(Chapter7) #2 | 状態ホイスティングの考え方に基づき、ToDoリストを管理するViewModelを実装する。 完了済みToDoの表示切り替えを題材に、状態の変更に応じて一覧表示を更新し、リストの更新と画面表示を連動させる実装手順を学ぶ。 データ入力用ダイアログを実装し、既存ToDoの編集処理までを含む基本的な入力・更新フローを習得する。 | 7.5 開発を進めよう ・Step 5 完了済みToDoの表示を切り替える ・Step 6 ToDoを編集する | ||||||||||||||||||||||
30 | 18 | ToDoアプリ(Chapter7) #3 | ダミーデータによる管理を、Roomデータベースを用いた永続化に置き換える。 Entity、Dao、Databaseを実装し、それぞれの役割とデータベース構成の基本を理解する。 ViewModelにRoomを用いた参照・保存処理を組み込み、アプリの状態とデータベースを連動させたデータ管理を実装する。 | 7.5 開発を進めよう ・Step 7 データベースに保存する | ||||||||||||||||||||||
31 | 19 | ToDoアプリ(Chapter7) #4 | DaoとViewModelの連携を通じて機能を拡張し、完了ToDoの物理削除処理を実装する。削除対象の条件整理やUI操作との対応付けを行い、データ操作の流れを理解する。 処理中の表示やデータ0件時の表示などを追加し、ユーザが状況を把握しやすい画面に仕上げる。 | 7.5 開発を進めよう ・Step 8 完了ToDoをデータベースから削除する ・Step 9 アプリを仕上げる(UXの向上) | ||||||||||||||||||||||
32 | 20 | ToDoアプリ(Chapter7) #5 | ToDoの順序を入れ替える機能を追加し、ViewModelで管理する状態とFlowによるデータ更新を応用した実装手順を学ぶ。あわせて、順序情報の保持や更新処理を通じて、一覧表示とデータ管理を連動させる設計の考え方を理解する。 Kotlinのcompanion object、可変長引数、引数なしwhenについて、課題演習を通じて理解を深める。 | 7.5 開発を進めよう ・Step 10 ToDoの順序を入れ替える(任意) 7.7 復習:Kotlinの理解度を高めよう ・課題1 companion objectについて理解度を高める ・課題2 可変長引数について理解度を高める ・課題3 引数なしのwhenについて理解度を高める | ■時間が余る場合 ・チェックの処理を、SwipeToDismissBoxにする https://developer.android.com/develop/ui/compose/touch-input/user-interactions/swipe-to-dismiss?hl=ja ■時間が足りない場合 ・Step 10をスキップする(なくても成り立つので) | |||||||||||||||||||||
33 | 21 | カメラアプリ(Chapter8) #1 | NavHostを用いた画面遷移の基本を学び、画面構成と遷移の流れを整理しながらアプリ全体の設計を行う。 カメラ機能に必要となる権限リクエスト処理を実装し、アプリ起動時の動作と画面表示の関係を理解する。 CameraXライブラリを用いてカメラプレビューを表示し、プレビュー表示に必要な基本構成と実装手順を習得する。 | 8.1 完成したアプリをイメージしよう 画面のイメージを見ながら、全体的な作業内容を想像する 8.5 開発を進めよう ・Step 1 アプリ構成を検討する ・Step 2 新規プロジェクトを作成する ・Step 3 画面作成の準備をする ・Step 4 権限リクエストをする ・Step 5 カメラプレビューを実装する | 物量が多い。無理そうなら次回に回す。学生のつまり具合で進捗を決める。 | |||||||||||||||||||||
34 | 22 | カメラアプリ(Chapter8) #2 | カメラプレビューから静止画を撮影し、撮影結果をアプリ内で扱うための基本的な実装手順を学ぶ。端末の回転などを考慮し、取り出した画像の向きや表示結果を適切に補正する方法を理解する。 撮影した静止画を画面に表示し、プレビュー画面から確認画面へつなぐ一連の処理フローを習得する。 | 8.5 開発を進めよう ・Step 5 カメラプレビューを実装する ・Step 6 静止画を撮影する ・Step 7 静止画を表示する | 調整しながら進める | |||||||||||||||||||||
35 | 23 | カメラアプリ(Chapter8) #3 | ML Kitを用いて撮影画像から文字列を認識する処理を実装する。 認識結果を画面に分かりやすく表示するため、検出位置の情報を利用して画像を加工し、文字列の位置を視覚的に表現する方法を学ぶ。 | 8.5 開発を進めよう ・Step 7 静止画を表示する ・Step 8 文字列を認識する ・Step 9 認識結果を表示する | 調整しながら進める | |||||||||||||||||||||
36 | 24 | カメラアプリ(Chapter8) #4 | ML Kitを用いてバーコード認識を実装し、認識結果を取得する処理手順を学ぶ。検出位置を画面に分かりやすく表現するため、画像加工による枠表示などの実装方法を理解する。 Kotlinのuse関数と無名オブジェクトについて、課題演習を通じて理解を深める。 | 8.5 開発を進めよう ・Step 10 バーコードを認識する 8.7 復習:Kotlinの理解度を高めよう ・課題1 無名オブジェクトの生成について理解度を高める ・課題2 use関数について理解度を高める | ■時間が足りない場合 ・Step8,9を続ける ・終わっている学生は、Step10を実施する。 ■時間が余る場合 ・画面に表示している画像を保存する機能を追加する。 | |||||||||||||||||||||
37 | 25 | 書籍検索アプリ(Chapter9) #1 | Webサービスを利用するアプリの完成イメージを確認し、必要となる技術要素を整理して全体像を把握する。 あわせて、JSONやWebサービスの基本概念を学び、アプリが外部サービスとデータをやり取りする前提知識を習得する。 さらに、NavHostを用いた画面遷移の構成を準備し、検索画面や結果表示画面など複数画面を持つアプリの土台を実装する。 | 9.1 完成したアプリをイメージしよう アプリ作成に必要そうな要素確認 9.5 開発を進めよう ・Step 1 アプリ作成に必要な知識を整理する ・Step 2 新規プロジェクトを作成する ・Step 3 画面作成の準備をする | JSONやHTTP通信と、ブラウザに表示されるデータから、処理のイメージをしてから次に進む。 ブラウザで、API起動し、レスポンスを見るとJSONがイメージしやすい。本書の通り進める。 ■ "code": 429,になる場合は APIキーを生成する手順を踏む。以下の補足記事参照。 https://github.com/genz0/android-compose-step-by-step | |||||||||||||||||||||
38 | 26 | 書籍検索アプリ(Chapter9) #2 | 固定文字列を用いたJSON解析を題材に、データ構造と処理ロジックを整理し、data classの定義と役割を理解する。 あわせて、JSONの内容に対応したdata classを設計し、解析結果からdata classのListを生成するまでの一連の実装手順を学ぶ。 | 9.5 開発を進めよう ・Step 4 データとロジックを整理する ・Step 5 JSONを解析する | 調整しながら進める | |||||||||||||||||||||
39 | 27 | 書籍検索アプリ(Chapter9) #3 | 解析したデータを使い、データの一覧表示画面を実装する。 一覧画面に表示した情報と連動した、詳細画面を実装する。 | 9.5 開発を進めよう ・Step 6 リスト画面を実装する ・Step 7 詳細画面を実装する | 調整しながら進める | |||||||||||||||||||||
40 | 28 | 書籍検索アプリ(Chapter9) #4 | ダミーデータによる検索処理を、Google Books APIから情報を取得する方式に置き換える。OkHttpを用いた通信処理を実装し、リクエスト送信からレスポンス受信までの流れを理解する。 手動で行っていた解析処理を見直し、Gsonを用いた自動解析に切り替えることで、data classとの対応付けと実装の簡略化を学ぶ。 | 9.5 開発を進めよう ・Step 8 Google Books APIを利用した検索処理に変更する ・Step 9 APIの結果をGsonで自動解析するように変更する ・Step 10 アプリを仕上げる(UXの向上) | 調整しながら進める | |||||||||||||||||||||
41 | 29 | 書籍検索アプリ(Chapter9) #5 | 書籍検索アプリの仕上げとしてUX向上を行い、サムネイル表示や通信中の状態表示など、ユーザが状況を把握しやすい画面に整える。 Kotlinのスコープ関数と安全なnullの扱い方について、課題演習を通じて理解を深める。 | 9.5 開発を進めよう ・Step 10 アプリを仕上げる(UXの向上) 9.7 復習:Kotlinの理解度を高めよう 課題1 スコープ関数の利用方法について理解度を高める 課題2 安全なnullの扱い方について理解度を高める | ■時間が余る場合 ・Google Books APIsのいろんなパラメータを使って検索する ・シンプルなページング機能を実装する ■時間が足りない場合 ・Step 10の後半(例外系の処理)を割愛する | |||||||||||||||||||||
42 | 30 | まとめ | これまでの振り返りを行う。 最後までやりきれなかった課題や、プラスアルファ部分の実装をする。 | 考査や、振り返りなどの実施。 | ||||||||||||||||||||||
43 | 教科書・教材 | |||||||||||||||||||||||||
44 | ノートPC、スマートフォン、参考書籍 | |||||||||||||||||||||||||
45 | 評価項目(評価の方法) | 評価率 | ||||||||||||||||||||||||
46 | 相対評価 | 100.0% | ||||||||||||||||||||||||
47 | ||||||||||||||||||||||||||
48 | ||||||||||||||||||||||||||
49 | 評価の観点 | |||||||||||||||||||||||||
50 | 【受講ルール】:資料は、書籍とその付属のコードをGithubから取得する。課題は指定された方法で期限までに提出する。 【評価の観点】:Androidアプリ開発の習得度、提出したコード 【評価項目(評価の方法)】:提出物の得点、授業態度などから総合的に評価する。 | |||||||||||||||||||||||||
51 | その他 | |||||||||||||||||||||||||
52 | ||||||||||||||||||||||||||
53 | ||||||||||||||||||||||||||
54 | ||||||||||||||||||||||||||
55 | ||||||||||||||||||||||||||
56 | ||||||||||||||||||||||||||
57 | ||||||||||||||||||||||||||
58 | ||||||||||||||||||||||||||
59 | ||||||||||||||||||||||||||
60 | ||||||||||||||||||||||||||
61 | ||||||||||||||||||||||||||
62 | ||||||||||||||||||||||||||
63 | ||||||||||||||||||||||||||
64 | ||||||||||||||||||||||||||
65 | ||||||||||||||||||||||||||
66 | ||||||||||||||||||||||||||
67 | ||||||||||||||||||||||||||
68 | ||||||||||||||||||||||||||
69 | ||||||||||||||||||||||||||
70 | ||||||||||||||||||||||||||
71 | ||||||||||||||||||||||||||
72 | ||||||||||||||||||||||||||
73 | ||||||||||||||||||||||||||
74 | ||||||||||||||||||||||||||
75 | ||||||||||||||||||||||||||
76 | ||||||||||||||||||||||||||
77 | ||||||||||||||||||||||||||
78 | ||||||||||||||||||||||||||
79 | ||||||||||||||||||||||||||
80 | ||||||||||||||||||||||||||
81 | ||||||||||||||||||||||||||
82 | ||||||||||||||||||||||||||
83 | ||||||||||||||||||||||||||
84 | ||||||||||||||||||||||||||
85 | ||||||||||||||||||||||||||
86 | ||||||||||||||||||||||||||
87 | ||||||||||||||||||||||||||
88 | ||||||||||||||||||||||||||
89 | ||||||||||||||||||||||||||
90 | ||||||||||||||||||||||||||
91 | ||||||||||||||||||||||||||
92 | ||||||||||||||||||||||||||
93 | ||||||||||||||||||||||||||
94 | ||||||||||||||||||||||||||
95 | ||||||||||||||||||||||||||
96 | ||||||||||||||||||||||||||
97 | ||||||||||||||||||||||||||
98 | ||||||||||||||||||||||||||
99 | ||||||||||||||||||||||||||
100 | ||||||||||||||||||||||||||