Gå til indholdet

N070 Hastighedskonvertering

Du skal designe et værktøj, der hjælper brugeren med at konvertere hastighed fra miles per hour (MPH) til kilometer i timen (KMT). Brugeren skal have mulighed for at indtaste en hastighed i MPH (som et heltal), og værktøjet skal derefter vise den tilsvarende hastighed i KMT (med eller uden decimaler). Formlen for konvertering er: KMT = MPH x 1.60934. Værktøjet skal først vise en besked, der beder brugeren om at indtaste en hastighed i MPH. Efter indtastning skal værktøjet vise den konverterede hastighed i KMT ved hjælp af den tidligere nævnte metode.

Information til undervisere

Dette er en opgave som typisk kan bruges til “fælles opgaveløsning” fordi der er elementer som kunne kræve en instruktør. Til sidst er en del ekstra tillæg som typisk viser forskellige teknologier.

Den kunne bruges som et afsluttende projekt efter en halv dags undervisning.

Eksempel på konsolinteraktion:

> Indtast hastighed i MPH: 60
> Resultat: 60 MPH er lig med 96,5604 KMT.

Version 1: Iterativ løsning (uden metode)

Opgaven kan løses på mange måder men prøv at løse den uden at tænke på genbrugelighed mv - bare skriv koden i sin første version.

Version 2: Procedural løsning (med metode)

For at sikre genbrugelighed og enkelhed i din løsning, anbefales det at oprette en særskilt metode, der håndterer konverteringen. Denne metode kan tage en hastighed i MPH som parameter og returnere den tilsvarende hastighed i KMT. Ved at isolere konverteringslogikken i sin egen metode gør du det nemmere at genbruge denne funktionalitet i fremtidige projekter eller udvide værktøjet med yderligere funktioner.

Prøv at skrive version 2.

Version 3: Fejlhåndtering

Metoden bør tjekke, om det indtastede input faktisk er et tal. Hvis ikke, bør den returnere en fejlmeddelelse. Yderligere bør den også tjekke for negative tal, da hastighed ikke kan være negativ. Hvis et negativt tal indtastes, bør en fejlmeddelelse returneres.

Eksempler på en fejlmeddelelse kunne være:

> Indtast hastighed i MPH: abc
> Du har indtastet en forkert værdi - programmet afsluttes
> Indtast hastighed i MPH: -6
> Du har indtastet en forkert værdi - programmet afsluttes

Prøv at skrive version 3.

Tips til C#

1. Udskrivning på konsol:

Console.WriteLine("Dette er en besked på konsollen.");

2. Hente input fra konsol:

string input = Console.ReadLine();

3. Typekonvertering: For at konvertere en streng til et heltal (int):

string numStr = "123";
int num = int.Parse(numStr);

4. Eksempel på en metode:

double ConvertMphToKmt(double mph)
{
    return mph * 1.60934;
}

5. Fejlhåndtering:

try
{
    int num = int.Parse(input);
}
catch (FormatException)
{
    Console.WriteLine("Input var ikke et gyldigt tal.");
}

Tips til Python

1. Udskrivning på konsol:

print("Dette er en besked på konsollen.")

2. Hente input fra konsol:

input_data = input("Indtast noget: ")

3. Typekonvertering: For at konvertere en streng til et heltal (int):

num_str = "123"
num = int(num_str)

4. Eksempel på en metode:

def convert_mph_to_kmt(mph):
    return mph * 1.60934

5. Fejlhåndtering:

try:
    num = int(input_data)
except ValueError:
    print("Input var ikke et gyldigt tal.")
Løsning i C#

Version 1: Iterativ løsning (uden metode)

using System;

Console.Write("Indtast hastighed i MPH: ");
string input = Console.ReadLine();
double mph = double.Parse(input);
double kmt = mph * 1.60934;
Console.WriteLine($"Resultat: {mph} MPH er lig med {kmt} KMT.");

Version 2: Procedural løsning (med metode)

using System;

Console.Write("Indtast hastighed i MPH: ");
string input = Console.ReadLine();
double mph = double.Parse(input);
double kmt = ConvertMphToKmt(mph);
Console.WriteLine($"Resultat: {mph} MPH er lig med {kmt} KMT.");

double ConvertMphToKmt(double mph)
{
    return mph * 1.60934;
}

Version 3: Fejlhåndtering

using System;

Console.Write("Indtast hastighed i MPH: ");
string input = Console.ReadLine();

try
{
    double mph = double.Parse(input);
    if (mph < 0)
    {
        Console.WriteLine("Hastighed kan ikke være negativ.");
        return;
    }
    double kmt = ConvertMphToKmt(mph);
    Console.WriteLine($"Resultat: {mph} MPH er lig med {kmt} KMT.");
}
catch (FormatException)
{
    Console.WriteLine("Input var ikke et gyldigt tal.");
}

double ConvertMphToKmt(double mph)
{
    return mph * 1.60934;
}
Løsning i Python

Version 1: Iterativ løsning (uden funktion)

input_data = input("Indtast hastighed i MPH: ")
mph = float(input_data)
kmt = mph * 1.60934
print(f"Resultat: {mph} MPH er lig med {kmt:.4f} KMT.")

Version 2: Procedural løsning (med funktion)

def convert_mph_to_kmt(mph):
    return mph * 1.60934

input_data = input("Indtast hastighed i MPH: ")
mph = float(input_data)
kmt = convert_mph_to_kmt(mph)
print(f"Resultat: {mph} MPH er lig med {kmt:.4f} KMT.")

Version 3: Fejlhåndtering

def convert_mph_to_kmt(mph):
    return mph * 1.60934

input_data = input("Indtast hastighed i MPH: ")

try:
    mph = float(input_data)
    if mph < 0:
        print("Hastighed kan ikke være negativ.")
    else:
        kmt = convert_mph_to_kmt(mph)
        print(f"Resultat: {mph} MPH er lig med {kmt:.4f} KMT.")
except ValueError:
    print("Input var ikke et gyldigt tal.")

Ekstra: WPF Brugerflade

Der er mange måder at skabe en brugerflade i .NET til alle platforme. På en ren Windows platform er WPF en af mulighederne. Prøv følgende i en tom mappe:

dotnet new wpf -n SpeedConverterWPF
cd SpeedConverterWPF

Tilret MainWindow.xaml til følgende

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Speed Converter" Height="200" Width="400">
    <Grid Margin="10">
        <Label Content="Enter speed in mph:" VerticalAlignment="Top" />
        <TextBox x:Name="mphTextBox" VerticalAlignment="Top" Margin="0,25,0,0" />
        <Button Content="Convert to kmt" VerticalAlignment="Top" Margin="0,60,0,0" Click="OnConvertClicked" />
        <Label x:Name="resultLabel" VerticalAlignment="Top" Margin="0,100,0,0" />
    </Grid>
</Window>

og MainWindow.cs til følgende

using System;
using System.Windows;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void OnConvertClicked(object sender, RoutedEventArgs e)
    {
        if (double.TryParse(mphTextBox.Text, out double mph))
        {
            try
            {
                double kmt = ConvertMphToKmt(mph);
                resultLabel.Content = $"Result: {kmt} kmt";
            }
            catch (ArgumentException ex)
            {
                resultLabel.Content = ex.Message;
            }
        }
        else
        {
            resultLabel.Content = "Please enter a valid number.";
        }
    }

    double ConvertMphToKmt(double mph)
    {
        return mph * 1.60934;
    }
}

Kør applikationen med

dotnet run

Ikke super køn og “UI-agtig” brugerflade men det er nemt at tilrette - især i værktøjer som VS.

Ekstra: Web

En web brugerflade kan eksempelvis skabes med ASP.NET MVC. Prøv følgende i en tom mappe:

dotnet new mvc -n SpeedConverterWebApp
cd SpeedConverterWebApp

Tilret herefter /Views/Home/Index.cshtml til

@{
    ViewData["Title"] = "Speed Converter";
}

<h2>@ViewData["Title"]</h2>

<form asp-action="Convert" method="post">
    <div>
        <label>Enter speed in mph:</label>
        <input type="text" name="mph" />
    </div>
    <div>
        <input type="submit" value="Convert to kmt" />
    </div>
</form>

@if (ViewBag.Result != null)
{
    <div>
        <strong>Result:</strong> @ViewBag.Result kmt
    </div>
}

og /Controllers/HomeController.cs til

using Microsoft.AspNetCore.Mvc;

public class HomeController : Controller
{

    [HttpGet("~/")]
    [HttpPost("~/")]
    public IActionResult Convert(double mph)
    {
        try
        {
            double kmt = ConvertMphToKmt(mph);
            ViewBag.Result = kmt;
        }
        catch (ArgumentException ex)
        {
            ViewBag.Result = ex.Message;
        }

        return View("Index");
    }
    [HttpGet("~/Privacy")]
    public IActionResult Privacy()
    {
        return View();
    }

    double ConvertMphToKmt(double mph)
    {
        return mph * 1.60934;
    }
}

Prøv herefter at køre applikationen med dotnet run. Det burde resultere i noget ala

PS C:\temp\SpeedConverterWebApp> dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5292
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\temp\SpeedConverterWebApp

hvorefter applikationen kan tilgås ved at indtaste http://localhost:5292 i en browser.

Ekstra: Unit test

Se i øvrigt denne side for at få en ide om hvordan unit test virker.

Ekstra: HTTP Service

Som eksempel på konvertering af opgaven så den benytter en HTTP service kan du hente et Docker image og kalde metoden over nettet i stedet. Se GitHub for at installere service (kræver Docker Desktop).

Når først tjenesten kører kan alle mulige klienter benytte den - her C# og Python.

Løsning i C#

using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;

const string ServiceUrl = "http://localhost:8080/api/speedconverter";

var client = new HttpClient();

// GET request
var responseJson = await client.GetFromJsonAsync<SpeedResponse>($"{ServiceUrl}?mph=60");
Console.WriteLine($"GET: {responseJson?.Mph} MPH er lig med {responseJson?.Kmt} KMT. Server tid: {responseJson?.ServerTime}");

// POST request
var data = new { Mph = 60 };
var postResponse = await client.PostAsJsonAsync(ServiceUrl, data);
var postResponseJson = await postResponse.Content.ReadFromJsonAsync<SpeedResponse>();
Console.WriteLine($"POST: {postResponseJson?.Mph} MPH er lig med {postResponseJson?.Kmt} KMT. Server tid: {postResponseJson?.ServerTime}");

public class SpeedResponse
{
    public double Mph { get; set; }
    public double Kmt { get; set; }
    public DateTime ServerTime { get; set; }
}

Løsning i Python

import requests

SERVICE_URL = "http://localhost:8080/api/speedconverter"

# GET request
response = requests.get(f"{SERVICE_URL}?mph=60")
response_json = response.json()
print(f"GET: {response_json['Mph']} MPH er lig med {response_json['Kmt']} KMT. Server tid: {response_json['ServerTime']}")

# POST request
data = {"Mph": 60}
post_response = requests.post(SERVICE_URL, json=data)
post_response_json = post_response.json()
print(f"POST: {post_response_json['Mph']} MPH er lig med {post_response_json['Kmt']} KMT. Server tid: {post_response_json['ServerTime']}")