public async Task <ActionResult> CollectFine(SpeedingViolation speedingViolation, [FromServices] DaprClient daprClient)
        {
            decimal fine = _fineCalculator.CalculateFine(_fineCalculatorLicenseKey, speedingViolation.ViolationInKmh);

            // get owner info
            var vehicleInfo = await _vehicleRegistrationService.GetVehicleInfo(speedingViolation.VehicleId);

            // log fine
            string fineString = fine == 0 ? "tbd by the prosecutor" : $"{fine} Euro";

            _logger.LogInformation($"Sent speeding ticket to {vehicleInfo.OwnerName}. " +
                                   $"Road: {speedingViolation.RoadId}, Licensenumber: {speedingViolation.VehicleId}, " +
                                   $"Vehicle: {vehicleInfo.Brand} {vehicleInfo.Model}, " +
                                   $"Violation: {speedingViolation.ViolationInKmh} Km/h, Fine: {fineString}, " +
                                   $"On: {speedingViolation.Timestamp.ToString("dd-MM-yyyy")} " +
                                   $"at {speedingViolation.Timestamp.ToString("hh:mm:ss")}.");

            // send fine by email
            var body     = EmailUtils.CreateEmailBody(speedingViolation, vehicleInfo, fineString);
            var metadata = new Dictionary <string, string>
            {
                ["emailFrom"] = "*****@*****.**",
                ["emailTo"]   = vehicleInfo.OwnerEmail,
                ["subject"]   = $"Speeding violation on the {speedingViolation.RoadId}"
            };
            await daprClient.InvokeBindingAsync("sendmail", "create", body, metadata);

            return(Ok());
        }
        public async Task <ActionResult> VehicleExit(VehicleRegistered msg, [FromServices] DaprClient daprClient)
        {
            try
            {
                // get vehicle state
                var vehicleState = await _vehicleStateRepository.GetVehicleStateAsync(msg.LicenseNumber);

                if (vehicleState == null)
                {
                    return(NotFound());
                }

                // log exit
                _logger.LogInformation($"EXIT detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")} " +
                                       $"of vehicle with license-number {msg.LicenseNumber}.");

                // update state
                vehicleState.ExitTimestamp = msg.Timestamp;
                await _vehicleStateRepository.SaveVehicleStateAsync(vehicleState);

                // handle possible speeding violation
                int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(
                    vehicleState.EntryTimestamp, vehicleState.ExitTimestamp);
                if (violation > 0)
                {
                    _logger.LogInformation($"Speeding violation detected ({violation} KMh) of vehicle" +
                                           $"with license-number {vehicleState.LicenseNumber}.");

                    var speedingViolation = new SpeedingViolation
                    {
                        VehicleId      = msg.LicenseNumber,
                        RoadId         = _roadId,
                        ViolationInKmh = violation,
                        Timestamp      = msg.Timestamp
                    };

                    // In last half of Assignment 3, update pub/sub to use Dapr ASP.NET Core client
                    //   argument #1: Name of pub/sub component
                    //   argument #2: Name of topic to which to publish
                    //   argument #3: The message payload
                    // publish speedingviolation
                    await daprClient.PublishEventAsync("pubsub", "collectfine", speedingViolation);

                    // pub/sub code from first-half of Assignment 3
                    // var message = JsonContent.Create<SpeedingViolation>(speedingViolation);
                    // // Replace the hardcoded API code with a call to the Dapr pub/sub side car
                    // await _httpClient.PostAsync("http://localhost:3600/v1.0/publish/pubsub/collectfine", message);
                    // //await _httpClient.PostAsync("http://localhost:6001/collectfine", message);
                }

                return(Ok());
            }
            catch
            {
                return(StatusCode(500));
            }
        }
Esempio n. 3
0
        public ActionResult SendFine(SpeedingViolation speedingViolation)
        {
            decimal fine = _fineCalculator.CalculateFine(speedingViolation.ViolationInKmh);

            string fineString = fine == 0 ? "tbd by the prosecutor" : $"{fine} Euro";

            _logger.LogInformation($"Sent speeding ticket. Road: {speedingViolation.RoadId}, Licensenumber: {speedingViolation.VehicleId}, " +
                                   $"Violation: {speedingViolation.ViolationInKmh} Km/h, Fine: {fineString}, On: {speedingViolation.Timestamp.ToString("dd-MM-yyyy")} " +
                                   $"at {speedingViolation.Timestamp.ToString("hh:mm:ss")}.");

            return(Ok());
        }
    public async Task <ActionResult> VehicleExitAsync(VehicleRegistered msg, [FromServices] DaprClient daprClient)
    {
        try
        {
            // get vehicle state
            var state = await _vehicleStateRepository.GetVehicleStateAsync(msg.LicenseNumber);

            if (state == default(VehicleState))
            {
                return(NotFound());
            }

            // log exit
            _logger.LogInformation($"EXIT detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")} " +
                                   $"of vehicle with license-number {msg.LicenseNumber}.");

            // update state
            var exitState = state.Value with {
                ExitTimestamp = msg.Timestamp
            };
            await _vehicleStateRepository.SaveVehicleStateAsync(exitState);

            // handle possible speeding violation
            int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(exitState.EntryTimestamp, exitState.ExitTimestamp.Value);
            if (violation > 0)
            {
                _logger.LogInformation($"Speeding violation detected ({violation} KMh) of vehicle" +
                                       $"with license-number {state.Value.LicenseNumber}.");

                var speedingViolation = new SpeedingViolation
                {
                    VehicleId      = msg.LicenseNumber,
                    RoadId         = _roadId,
                    ViolationInKmh = violation,
                    Timestamp      = msg.Timestamp
                };

                // publish speedingviolation (Dapr publish / subscribe)
                await daprClient.PublishEventAsync("pubsub", "speedingviolations", speedingViolation);
            }

            return(Ok());
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error occurred while processing EXIT");
            return(StatusCode(500));
        }
    }
Esempio n. 5
0
        public async Task <ActionResult> CollectFine(SpeedingViolation speedingViolation, [FromServices] DaprClient daprClient)
        // Replace the SpeedingViolation with a JsonDocument parameter. Doing so will enable Dapr pub/sub messaging.
        //public async Task<ActionResult> CollectFine([FromBody] System.Text.Json.JsonDocument cloudevent)
        {
            // Remove CloudEvent parsing code when using ASP.NET Core Dapr client
            // // Extract SpeedingViolation data from the cloudevent parameter and assign to SpeedingViolation type.
            // var data = cloudevent.RootElement.GetProperty("data");

            // // Transform raw data into a SpeedingViolation object
            // var speedingViolation = new SpeedingViolation
            // {
            //     VehicleId = data.GetProperty("vehicleId").GetString(),
            //     RoadId = data.GetProperty("roadId").GetString(),
            //     Timestamp = data.GetProperty("timestamp").GetDateTime(),
            //     ViolationInKmh = data.GetProperty("violationInKmh").GetInt32()
            // };

            decimal fine = _fineCalculator.CalculateFine(_fineCalculatorLicenseKey, speedingViolation.ViolationInKmh);

            // get owner info
            var vehicleInfo = await _vehicleRegistrationService.GetVehicleInfo(speedingViolation.VehicleId);

            // log fine
            string fineString = fine == 0 ? "tbd by the prosecutor" : $"{fine} Euro";

            _logger.LogInformation($"Sent speeding ticket to {vehicleInfo.OwnerName}. " +
                                   $"Road: {speedingViolation.RoadId}, Licensenumber: {speedingViolation.VehicleId}, " +
                                   $"Vehicle: {vehicleInfo.Brand} {vehicleInfo.Model}, " +
                                   $"Violation: {speedingViolation.ViolationInKmh} Km/h, Fine: {fineString}, " +
                                   $"On: {speedingViolation.Timestamp.ToString("dd-MM-yyyy")} " +
                                   $"at {speedingViolation.Timestamp.ToString("hh:mm:ss")}.");

            // send fine by email
            // Create email body with custom EmailUtility class
            var body = EmailUtils.CreateEmailBody(speedingViolation, vehicleInfo, fineString);

            // Specify email metadata
            var metadata = new Dictionary <string, string>
            {
                ["emailFrom"] = "*****@*****.**",
                ["emailTo"]   = vehicleInfo.OwnerEmail,
                ["subject"]   = $"Speeding violation on the {speedingViolation.RoadId}"
            };

            // Call email server with Dapr output binding
            await daprClient.InvokeBindingAsync("sendmail", "create", body, metadata);

            return(Ok());
        }
        public async Task <ActionResult> VehicleExit(VehicleRegistered msg)
        {
            try
            {
                // get vehicle state
                var vehicleState = await _vehicleStateRepository.GetVehicleStateAsync(msg.LicenseNumber);

                if (vehicleState == null)
                {
                    return(NotFound());
                }

                // log exit
                _logger.LogInformation($"EXIT detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")} " +
                                       $"of vehicle with license-number {msg.LicenseNumber}.");

                // update state
                vehicleState.ExitTimestamp = msg.Timestamp;
                await _vehicleStateRepository.SaveVehicleStateAsync(vehicleState);

                // handle possible speeding violation
                int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(
                    vehicleState.EntryTimestamp, vehicleState.ExitTimestamp);
                if (violation > 0)
                {
                    _logger.LogInformation($"Speeding violation detected ({violation} KMh) of vehicle" +
                                           $"with license-number {vehicleState.LicenseNumber}.");

                    var speedingViolation = new SpeedingViolation
                    {
                        VehicleId      = msg.LicenseNumber,
                        RoadId         = _roadId,
                        ViolationInKmh = violation,
                        Timestamp      = msg.Timestamp
                    };

                    // publish speedingviolation
                    var message = JsonContent.Create <SpeedingViolation>(speedingViolation);
                    await _httpClient.PostAsync("http://localhost:5001/collectfine", message);
                }

                return(Ok());
            }
            catch
            {
                return(StatusCode(500));
            }
        }
Esempio n. 7
0
        public async Task <ActionResult> VehicleExit(
            VehicleRegistered msg,
            //[FromState(DAPR_STORE_NAME)]StateEntry<VehicleInfo> state,
            [FromServices] DaprClient daprClient)
        {
            try
            {
                // get vehicle state
                var state = await daprClient.GetStateEntryAsync <VehicleState>(DAPR_STORE_NAME, msg.LicenseNumber);

                if (state.Value == null)
                {
                    return(NotFound());
                }

                // log exit
                _logger.LogInformation($"EXIT detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")}: " +
                                       $"{state.Value.Brand} {state.Value.Model} with license-number {msg.LicenseNumber}.");

                // update state
                state.Value.ExitTimestamp = msg.Timestamp;
                await state.SaveAsync();

                // handle possible speeding violation
                int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(state.Value.EntryTimestamp, state.Value.ExitTimestamp);
                if (violation > 0)
                {
                    _logger.LogInformation($"Speeding violation detected ({violation} KMh) of {state.Value.Brand} {state.Value.Model} " +
                                           $"with license-number {state.Value.LicenseNumber}.");

                    var speedingViolation = new SpeedingViolation
                    {
                        VehicleId      = msg.LicenseNumber,
                        RoadId         = _roadId,
                        ViolationInKmh = violation,
                        Timestamp      = msg.Timestamp
                    };
                    await _governmentService.SendFine(speedingViolation);
                }

                return(Ok());
            }
            catch
            {
                return(Ok(new { status = "RETRY" }));
            }
        }
Esempio n. 8
0
    public async Task RegisterExitAsync(VehicleRegistered msg)
    {
        try
        {
            Logger.LogInformation($"EXIT detected in lane {msg.Lane} at " +
                                  $"{msg.Timestamp.ToString("hh:mm:ss")} " +
                                  $"of vehicle with license-number {msg.LicenseNumber}.");

            // remove lost vehicle timer
            await UnregisterReminderAsync("VehicleLost");

            // get vehicle state
            var vehicleState = await this.StateManager.GetStateAsync <VehicleState>("VehicleState");

            vehicleState = vehicleState with {
                ExitTimestamp = msg.Timestamp
            };
            await this.StateManager.SetStateAsync("VehicleState", vehicleState);

            // handle possible speeding violation
            int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(
                vehicleState.EntryTimestamp, vehicleState.ExitTimestamp.Value);
            if (violation > 0)
            {
                Logger.LogInformation($"Speeding violation detected ({violation} KMh) of vehicle " +
                                      $"with license-number {vehicleState.LicenseNumber}.");

                var speedingViolation = new SpeedingViolation
                {
                    VehicleId      = msg.LicenseNumber,
                    RoadId         = _roadId,
                    ViolationInKmh = violation,
                    Timestamp      = msg.Timestamp
                };

                // publish speedingviolation (Dapr publish / subscribe)
                await _daprClient.PublishEventAsync("pubsub", "speedingviolations", speedingViolation);
            }
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "Error in RegisterExit");
        }
    }
        public async Task <ActionResult> CollectFine(SpeedingViolation speedingViolation)
        {
            decimal fine = _fineCalculator.CalculateFine(_fineCalculatorLicenseKey, speedingViolation.ViolationInKmh);

            // get owner info
            var vehicleInfo = await _vehicleRegistrationService.GetVehicleInfo(speedingViolation.VehicleId);

            // log fine
            string fineString = fine == 0 ? "tbd by the prosecutor" : $"{fine} Euro";

            _logger.LogInformation($"Sent speeding ticket to {vehicleInfo.OwnerName}. " +
                                   $"Road: {speedingViolation.RoadId}, Licensenumber: {speedingViolation.VehicleId}, " +
                                   $"Vehicle: {vehicleInfo.Brand} {vehicleInfo.Model}, " +
                                   $"Violation: {speedingViolation.ViolationInKmh} Km/h, Fine: {fineString}, " +
                                   $"On: {speedingViolation.Timestamp.ToString("dd-MM-yyyy")} " +
                                   $"at {speedingViolation.Timestamp.ToString("hh:mm:ss")}.");

            // send fine by email
            // TODO

            return(Ok());
        }
Esempio n. 10
0
    public static string CreateEmailBody(
        SpeedingViolation speedingViolation,
        VehicleInfo vehicleInfo,
        string fine)
    {
        return($@"
                <html>
                    <head>
                        <style>
                            body {{
                                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                            }}
                            table {{ 
								text-align: left;
								padding-top: 10px;
                            }}
                            th {{
								width: 200px;
								padding-left: 10px;
								background-clip: content-box;
                                background-color: #EEEEEE;
								font-weight: normal;
                            }}
							td {{
								padding: 5px;
								width: 300px;
                                border: 1px solid black;
							}}
							.fine {{
								font-weight: bold;
								color: #FF0000;
							}}
							.logo {{
								float: left;
								display: block;
								margin-top: -15px;
							}}
							.title {{
								display: block;
							}}
							.logo-name {{
								color: #FFFFFF;
								background-color: #2AA3D9;
								vertical-align: middle;
								padding: 10px;
								margin-top: 20px;
								height: 20px;
								width: 400px;
							}}
							.logo-bar {{
								background-color: #005D91;
								width: 420px;
								height: 20px;
								margin-top: -22px;
								margin-bottom: 30px;
							}}
                        </style>
                    </head>
                    <body>
						<div class='logo'>
							<svg version='1.1' width='105px' height='85px' viewBox='-0.5 -0.5 105 85'><defs/><g><path d='M 25.51 71.39 L 45.51 31.2 L 97.04 31.2 L 77.04 71.39 Z' fill='#000000' stroke='none' transform='translate(2,3)rotate(-15,61.27,51.29)' opacity='0.25'/><path d='M 25.51 71.39 L 45.51 31.2 L 97.04 31.2 L 77.04 71.39 Z' fill='#e6e6e6' stroke='none' transform='rotate(-15,61.27,51.29)' pointer-events='all'/><path d='M 15.51 60.24 L 35.51 20.05 L 87.04 20.05 L 67.04 60.24 Z' fill='#000000' stroke='none' transform='translate(2,3)rotate(-15,51.27,40.14)' opacity='0.25'/><path d='M 15.51 60.24 L 35.51 20.05 L 87.04 20.05 L 67.04 60.24 Z' fill='#2aa3d9' stroke='none' transform='rotate(-15,51.27,40.14)' pointer-events='all'/><path d='M 4.39 49.08 L 24.39 8.89 L 75.92 8.89 L 55.92 49.08 Z' fill='#000000' stroke='none' transform='translate(2,3)rotate(-15,40.16,28.99)' opacity='0.25'/><path d='M 4.39 49.08 L 24.39 8.89 L 75.92 8.89 L 55.92 49.08 Z' fill='#005d91' stroke='none' transform='rotate(-15,40.16,28.99)' pointer-events='all'/></g></svg>
						</div>
						<div class='title'>
							<h4 class='logo-name'>Central Fine Collection Agency</h4>
							<div class='logo-bar'>&nbsp;</div>
						</div>
                        <p>The Hague, {DateTime.Now.ToLongDateString()}</p>
                        
                        <p>Dear Mr. / Miss / Mrs. {vehicleInfo.OwnerName},</p>
                        
                        <p>We hereby inform you of the fact that a speeding violation was detected with a 
                        vehicle that is registered to you.</p>
						
						<p>The violation was detected by a speeding camera. We have a digital image of your 
                        vehicle committing the violation on record in our system. If requested by your 
                        solicitor, we will provide this image to you.</p>

						<hr/>
						
						<p>Below you can find all the details of the violation.</p>

                        <p>
                            <b>Vehicle information:</b>
                            <table>
                                <tr><th>License number</th><td>{vehicleInfo.VehicleId}</td></tr>
                                <tr><th>Brand</th><td>{vehicleInfo.Brand}</td></tr>
                                <tr><th>Model</th><td>{vehicleInfo.Model}</td></tr>
                            </table>
                        </p>

                        <p>
                            <b>Conditions during the violation:</b>
                            <table>
                                <tr><th>Road</th><td>{speedingViolation.RoadId}</td></tr>
                                <tr><th>Date</th><td>{speedingViolation.Timestamp.ToString("dd-MM-yyyy")}</td></tr>
                                <tr><th>Time of day</th><td>{speedingViolation.Timestamp.ToString("hh:mm:ss")}</td></tr>
                            </table>							
                        </p>
						
                        <p>
                            <b>Sanction:</b>
                            <table>
                                <tr><th>Maximum speed violation</th><td>{speedingViolation.ViolationInKmh} KMh</td></tr>
                                <tr><th>Sanction amount</th><td><div class='fine'>{fine}</div></td></tr>
                            </table>							
                        </p>		

						<hr/>
							
						<p><b>Sanction handling:</b></p>
							
						<p>If the amount of the fine is to be determined by the prosecutor, you will receive a notice 
                        to appear in court shortly.</p>
						
                        <p>Otherwise, you must pay the sanctioned fine <b>within 8 weeks</b> after the date of this 
                        email. If you fail to pay within 8 weeks, you will receive a first reminder email and <b>the 
                        fine will be increased to 1.5x the original fine amount</b>. If you fail to pay within 8 weeks 
                        after the first reminder, you will receive a second and last reminder email and <b>the fine 
                        will be increased to 3x the original fine amount</b>. If you fail to pay within 8 weeks 
                        after the second reminder, the case is turned over to the prosecutor and you will receive a 
                        notice to appear in court.</p>

						<hr/>
									
						<p>
						Yours sincerely,<br/>
						The Central Fine Collection Agency
						</p>
                    </body>
                </html>
            ");
    }
 public async Task SendFine(SpeedingViolation speedingViolation)
 {
     await _httpClient.PostAsJsonAsync <SpeedingViolation>(
         $"collection/sendfine", speedingViolation, _serializerOptions);
 }