情報応用演習Ⅰ(2024)

【課題6-02】時間単位変換

プロジェクトタイプASP.NET Core Web アプリ(Model-View-Controller)
プロジェクト名Prac_6_02
ソリューション名PIT6x
ターゲットフレームワーク.NET 8.0(長期的なサポート)
最上位レベルのステートメントを使用しない使用する(チェックオフ)
訂正
  • 2024-06-10訂正: TimeUnitConversionアクションにGETでアクセスした際の入力欄の初期値を訂正いたしました.正→,誤→
    • (掲載期間が長かったのでどちらで実装していても正解といたします.)
今回の課題について
  • 作業成果物とは別のソリューションとなるので注意すること!!
    • 作業成果物とはソリューション名が異なる.
      • 作業成果物→PIT6
      • プログラミング課題→PIT6x
  • 今回の課題はWebClassに提出場所があるのでそちらに提出すること.
    • 今までの課題と異なり今回の課題はリアクションペーパーに記載するものではないことに注意せよ.
  • これらはすべて課題点として成績に算入される課題である.
    • 加点要素ではなく 必須の課題である ことに注意せよ.

時間を秒で入力して,それを選択した時間単位(秒,分,時間,日)で表示する Web アプリケーションを作成せよ. 画面の挙動については_をよく見て実装すること

画面イメージ
注意
  • やりかたによらず 自分以外(他の学生,学外の協力者,生成AIなど)が作成したソースコードを自身の成果物として提出してはならない
    • 違反が発覚した場合,その課題の評点と同じだけ成績から引くこととする.他の学生と回答を共有した場合は,元がどちらであるかに関わらず両者とも同じ処分とする. 課題は独力で取り組みむこと

全ての処理はデフォルトで作成されるHomeコントローラーで行う. 各アクションの処理内容を_に示す. 後述するように,この設問では Home コントローラーのソースコードはあらかじめ与えられている.これを改変することなく用いること.

Homeコントローラーのアクション
アクションGET メソッドでアクセスした際の機能POST メソッドでアクセスした際の機能
Index
TimeUnitConversion アクションへのリンクを表示する.

備考: ビューのテンプレートあり(後述)
(POSTでのアクセスはしない)
TimeUnitConversionフォームの表示

備考 : 入力欄にはあらかじめ以下のように入力されている状態とすること.
・「変換元の時間(秒)」→0
・「変換先の時間単位」→
計算結果の表示.以下のフォーマットで表示すること.

結果: 変換元の時間(秒) 秒 = 変換結果 変換先の時間単位

ここで変換結果変換元の時間(秒)変換先の時間単位の単位で表現した際の時間の長さである.変換先の時間単位は常に 小数点第二位まで表示すること

備考1 : GETとビューは共通
備考2 : 入力欄にはあらかじめ以下のように入力されている状態とすること.
・「変換元の時間(秒)」→以前に入力した値
・「変換先の時間単位」→以前に入力した値
AccessErrorアクセスエラーの表示(POSTでのアクセスはしない)

esこのアプリでは_に示す情報を取り扱う必要がある.このために _に示すクラスをもとにしたデータモデルを使用すること. 必要なデータアノテーションは自分で設定すること

このアプリで扱う情報
項目名(表示名)必須/任意データ型備考
変換元の時間(秒)必須整数0以上,上限なし(ヒント参照)
変換先の時間単位必須列挙型時間の単位を表す列挙型( 後述のTimeUnit列挙型 ).以下のいずれかを選択できる.
・秒・分・時間・日
データモデル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.ComponentModel.DataAnnotations;

namespace Prac_6_02.Models
{
    // 時間単位を表す列挙型
    public enum TimeUnit 
    {
        Seconds, // 秒

        Minutes, // 分

        Hours,   // 時間

        Days,    // 日
    }

    public class TimeInfo
    {
        public int TimeInSec { get; set; } // 変換元の時間(秒)

        public TimeUnit Unit { get; set; } // 変換先の時間単位
    }    
}

準備作業

プロジェクトを作成したら以下の準備作業を行こと

  • 【作業Ⅰ】 作業対象:プロジェクトPrac_6_02
    • 必要なパッケージをインストールする(後述).
  • 【作業Ⅱ】 作業対象:Views/Shared/_Layout.cshtml(ファイル)
  • 【作業Ⅲ】 作業対象:wwwroot/css/site.css(ファイル)
    • 必要なスタイル指定を追記する(後述).
  • 【作業Ⅳ】 作業対象:Homeコントローラー&ビュー
    • AccessErrorアクションを作成する(参考:リスト4b-6-3).
    • ↑に対応するビューを作成する(参考:リスト4b-6-4).
    • Indexアクションのビューに追記する(後述).
  • 【作業Ⅴ】 作業対象:Program.cs(ファイル)
【作業Ⅰ】
【作業Ⅰ】

NuGetを使って以下のパッケージを探してプロジェクトにインストールする. バージョンが選択可能な場合は「 最新の安定板 」を選択するのを忘れないようにしよう.

パッケージソースパッケージ名本校執筆時の安定版
knzw.techKnzwTech.AspNetCore.ResourceBasedLocalization.ja6.0.1
【作業Ⅰ】 : 閉じる
【作業Ⅱ】
【作業Ⅱ】

チュートリアル【T4a】を参考に以下のことを行う.

  • Views/Shared/_Layout.cshtml をリスト4a-4-2に示すように変更する.
  • ↑の6行目の T4aPrac_6_02 に変更し,サイトタイトルの部分を 【課題6-02】 に変更する.
【作業Ⅱ】 : 閉じる
【作業Ⅲ】
【作業Ⅲ】

wwwroot/css/site.css の末尾に_を追記する.

wwwroot/css/site.cssの追記内容
1
body { padding : 1em; }
【作業Ⅲ】 : 閉じる
【作業Ⅳ】
【作業Ⅳ】

チュートリアル【T4b】を参考に以下のことを行う.

  • Home コントローラーにリスト4b-6-3のアクションメソッド AccessError を追記する.
  • プロジェクト内の Views フォルダの Home フォルダに新規に AccessError という名前のビュー(.cshtmlファイル)を追加し,リスト4b-6-4の内容を書き込む
  • Views/Home/Index.cshtml を_の通りに書き換える.
Views/Home/Index.cshtmlの内容
1
2
3
4
5
@{
    ViewData["Title"] = "Home Page";
}

<a asp-action="TimeUnitConversion">時間単位変換へ</a>
【作業Ⅳ】 : 閉じる
【作業Ⅴ】
【作業Ⅴ】

チュートリアル【T4b】を参考に Program.cs を_に示すように編集する.

Program.csの内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using KnzwTech.AspNetCore.ResourceBasedLocalization;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews(opt => opt.EnableDefaultErrorMessagesFromResource());

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();

app.UseStatusCodePagesWithReExecute("/Home/AccessError/{0}");

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
【作業Ⅴ】 : 閉じる

各種テンプレート

いくつかのファイルに関しては以下のテンプレートを使用すること.

Controllers/HomeController.cs

Controllers/HomeController.cs は_を使用すること.

Controllers/HomeController.cs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using System.Diagnostics;
using Prac_6_02.Models;

namespace Prac_6_02.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        // AccessErrorアクション(GETのみ)
        public IActionResult AccessError(int? id)
        {
            if (id == null)
                return NotFound();

            int statusCode = id.Value;

            ViewBag.StatusCode = statusCode;
            ViewBag.ReasonPhrase = ReasonPhrases.GetReasonPhrase(statusCode);

            return View();
        }

        // TimeUnitConversion アクション(GET用)
        public IActionResult TimeUnitConversion() 
        {
            return View(new TimeInfo());
        }

        // TimeUnitConversion アクション(POST用)
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult TimeUnitConversion(TimeInfo timeInfo)
        {
            if (ModelState.IsValid) 
            {
                ViewData["result"] = Math.Round(timeInfo.TimeInSec / (double)timeInfo.Unit, 2);
            }//if

            return View(timeInfo);
        }
    }
}
Controllers/HomeController.cs : 閉じる

実行結果

正しく実装できた場合,実行結果は_のようになる (制作の都合上,動画ではプロジェクト名などが異なるが提出物では冒頭の指定を守ること).

実行結果

ヒント

  • 数値を小数点以下の桁数を指定して文字列化する方法はいくつかありうるが,フォーマット指定をともなう挿入文字列($で始まる文字列)を用いるのが最も簡単な方法である.
    • 挿入文字列には,文字列内に変数など式の内容を組み込むことができるが,その際の式の内容をどのようにフォーマットするかを指定することが可能である.
    • 参考:String interpolation in C# - C# | Microsoft Learn
  • 挿入文字列内でのフォーマット指定に関する文法を_に,使用例を_に示す.
    • 埋め込みたい変数・定数・式 ... その文字列に埋め込みたい変数など
    • アラインメント ... その変数の内容を何文字分で表示するかを整数で指定する
    • フォーマット文字列 ... その変数の内容をどのように表示するか(型により指定方法が異なる)
  • フォーマット文字列の指定方法は型ごとに異なる.詳細についてはOverview: How to format numbers, dates, enums, and other types in .NET - .NET | Microsoft Learnを参照せよ.
フォーマット指定
フォーマット指定の記述例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 以下のコードはあらかじめ double 型の変数 xyzzy が
// 宣言・初期化されていることを前提としている.

string hoge = $"あいうえお{xyzzy}かきくけこ";       // ←記述例1) フォーマット指定なし
string piyo = $"さしすせそ{xyzzy,8}たちつてと";     // ←記述例2) 8文字分(右寄せ)で文字列化
string fuga = $"なにぬねの{xyzzy:0.000}はひふへほ"; // ←記述例3) 小数点3位まで文字列化
string puyo = $"まみむめも{xyzzy,8:0.000}やゆよ";   // ←記述例4) 小数点3位までを8文字分(右寄せ)で文字列化
string hoga = $"らりるれろ{xyzzy,-8:0.000}わをん";  // ←記述例5) 小数点3位までを8文字分(左寄せ)で文字列化

//
// ■変数 xyzzy の値が 3.1415 である場合のフォーマット結果
//
// 記述例1の結果(変数 hoge の内容) → あいうえお3.1415かきくけこ
// 記述例2の結果(変数 piyo の内容) → さしすせそ  3.1415たちつてと
// 記述例3の結果(変数 fuga の内容) → なにぬねの3.142はひふへほ
// 記述例4の結果(変数 puyo の内容) → まみむめも   3.142やゆよ
// 記述例5の結果(変数 hoga の内容) → らりるれろ3.142   わをん
//
Last updated on 2024-06-10
Published on 2024-06-10

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.