Skip to content
This repository has been archived by the owner on Apr 12, 2023. It is now read-only.

調査内容の送信を実装 #1165

Merged
3 commits merged into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Covid19Radar/Covid19Radar/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ private static void RegisterCommonTypes(IContainer container)
// Utilities
container.Register<IDateTimeUtility, DateTimeUtility>(Reuse.Singleton);
container.Register<IDeviceInfoUtility, DeviceInfoUtility>(Reuse.Singleton);

// End of service
container.Register<ISurveyService, SurveyService>(Reuse.Singleton);
}

protected override void OnStart()
Expand Down
25 changes: 25 additions & 0 deletions Covid19Radar/Covid19Radar/Model/SurveyContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Covid19Radar.Model
{
public class SurveyContent
{
[JsonProperty("q1")]
public int Q1 { get; set; }

[JsonProperty("q2")]
public int Q2 { get; set; }

[JsonProperty("q3")]
public long Q3 { get; set; }

[JsonProperty("exposure_data")]
public SurveyExposureData ExposureData { get; set; }
}
}

23 changes: 23 additions & 0 deletions Covid19Radar/Covid19Radar/Model/SurveyExposureData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System;
using Chino;
using Newtonsoft.Json;
using System.Collections.Generic;

namespace Covid19Radar.Model
{
public class SurveyExposureData
{
[JsonProperty("en_version")]
public string EnVersion { get; set; }

[JsonProperty("daily_summaries")]
public List<DailySummary> DailySummaryList { get; set; }

[JsonProperty("exposure_windows")]
public List<ExposureWindow> ExposureWindowList { get; set; }
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum SendEventLogState
public class EventType
{
public static readonly EventType ExposureNotified = new EventType("ExposureNotification", "ExposureNotified");
public static readonly EventType Survey = new EventType("survey", "survey");

public static readonly EventType[] All = new EventType[] {
ExposureNotified
Expand Down
8 changes: 8 additions & 0 deletions Covid19Radar/Covid19Radar/Services/DialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ await AlertAsync(
AppResources.ButtonOk);
}

public async Task ShowNetworkConnectionErrorAsync()
{
await UserDialogs.Instance.AlertAsync(
Resources.AppResources.DialogNetworkConnectionError,
Resources.AppResources.DialogNetworkConnectionErrorTitle,
Resources.AppResources.ButtonOk);
}

public async Task<bool> ConfirmAsync(string message, string title = null, string okText = null, string cancelText = null) =>
await UserDialogs.Instance.ConfirmAsync(message, title, okText, cancelText);

Expand Down
9 changes: 8 additions & 1 deletion Covid19Radar/Covid19Radar/Services/EventLogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ namespace Covid19Radar.Services
{
public interface IEventLogService
{
public Task SendAllAsync(long maxSize, int maxRetry);
Task SendAllAsync(long maxSize, int maxRetry);
Task<bool> SendAsync(EventLog eventLog);
}

public class EventLogService : IEventLogService
Expand Down Expand Up @@ -184,5 +185,11 @@ private async Task<bool> SendAsync(string idempotencyKey, List<EventLog> eventLo
_loggerService.Error("Send event log failure");
return false;
}

public async Task<bool> SendAsync(EventLog eventLog)
{
string idempotencyKey = Guid.NewGuid().ToString();
return await SendAsync(idempotencyKey, new List<EventLog> { eventLog });
}
}
}
5 changes: 5 additions & 0 deletions Covid19Radar/Covid19Radar/Services/EventLogServiceNop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ public Task SendAllAsync(long maxSize, int maxRetry)
// do nothing
return Task.FromResult(new List<EventLog>());
}

public Task<bool> SendAsync(EventLog eventLog)
{
return Task.FromResult(true);
}
}
}
1 change: 1 addition & 0 deletions Covid19Radar/Covid19Radar/Services/IDialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ public interface IDialogService
Task<bool> ShowLocalNotificationOffWarningAsync();
Task ShowUserProfileNotSupportAsync();
Task ShowEventLogSaveCompletedAsync();
Task ShowNetworkConnectionErrorAsync();
}
}
87 changes: 87 additions & 0 deletions Covid19Radar/Covid19Radar/Services/SurveyService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System;
using Chino;
using Covid19Radar.Model;
using System.Collections.Generic;
using System.Threading.Tasks;
using Covid19Radar.Repository;
using Newtonsoft.Json.Linq;

namespace Covid19Radar.Services
{
public interface ISurveyService
{
Task<SurveyContent> BuildSurveyContent(int q1, int q2, DateTime q3, bool isExposureDataProvision);
Task<bool> SubmitSurvey(SurveyContent surveyContent);
}

public class SurveyService : ISurveyService
{
private readonly IEventLogService _eventLogService;
private readonly IExposureDataRepository _exposureDataRepository;
private readonly AbsExposureNotificationApiService _exposureNotificationApiService;

public SurveyService(
IEventLogService eventLogService,
IExposureDataRepository exposureDataRepository,
AbsExposureNotificationApiService exposureNotificationApiService
)
{
_eventLogService = eventLogService;
_exposureDataRepository = exposureDataRepository;
_exposureNotificationApiService = exposureNotificationApiService;
}

public async Task<SurveyContent> BuildSurveyContent(int q1, int q2, DateTime q3, bool isExposureDataProvision)
{
var surveyContent = new SurveyContent
{
Q1 = q1,
Q2 = q2,
Q3 = q3.ToUnixEpoch(),
ExposureData = isExposureDataProvision ? await GetExopsureData() : null
};
return surveyContent;
}

private async Task<SurveyExposureData> GetExopsureData()
{
try
{
long enVersion = await _exposureNotificationApiService.GetVersionAsync();
List<DailySummary> dailySummaryList = await _exposureDataRepository.GetDailySummariesAsync();
List<ExposureWindow> exposureWindowList = await _exposureDataRepository.GetExposureWindowsAsync();

var exposureData = new SurveyExposureData
{
EnVersion = enVersion.ToString(),
DailySummaryList = dailySummaryList,
ExposureWindowList = exposureWindowList
};

return exposureData;
}
catch
{
return null;
}
}

public async Task<bool> SubmitSurvey(SurveyContent surveyContent)
{
var eventLog = new EventLog
{
HasConsent = true,
Epoch = DateTime.UtcNow.ToUnixEpoch(),
Type = EventType.Survey.Type,
Subtype = EventType.Survey.SubType,
Content = JObject.FromObject(surveyContent),
};

return await _eventLogService.SendAsync(eventLog);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Covid19Radar.Common;
using Covid19Radar.Model;
using Covid19Radar.Repository;
using Covid19Radar.Services;
using Covid19Radar.Services.Logs;
using Covid19Radar.Views.EndOfService;
using Prism.Navigation;
Expand Down Expand Up @@ -47,6 +49,20 @@ public int SelectedIndexQ2
}
}

private SurveyAnswerPickerItem _selectedItemQ1;
public SurveyAnswerPickerItem SelectedItemQ1
{
get => _selectedItemQ1;
set => SetProperty(ref _selectedItemQ1, value);
}

private SurveyAnswerPickerItem _selectedItemQ2;
public SurveyAnswerPickerItem SelectedItemQ2
{
get => _selectedItemQ2;
set => SetProperty(ref _selectedItemQ2, value);
}

private DateTime _q3Answer;
public DateTime Q3Answer
{
Expand All @@ -60,16 +76,26 @@ public DateTime Q3Answer
}
}

private bool _isExposureDataProvision;
public bool IsExposureDataProvision
{
get => _isExposureDataProvision;
set => SetProperty(ref _isExposureDataProvision, value);
}

public bool IsTerminationOfUsePageButtonEnabled
=> _selectedIndexQ1 > 0 && _selectedIndexQ2 > 0 && _q3Answer != null;

private readonly IUserDataRepository _userDataRepository;
private readonly ISurveyService _surveyService;

public SurveyPageViewModel(
INavigationService navigationService,
ISurveyService surveyService,
IUserDataRepository userDataRepository
) : base(navigationService)
{
_surveyService = surveyService;
_userDataRepository = userDataRepository;
}

Expand All @@ -83,11 +109,19 @@ public override void Initialize(INavigationParameters parameters)

DateTime startDate = _userDataRepository.GetStartDate();
Q3Answer = startDate.ToLocalTime();

IsExposureDataProvision = false;
}

public IAsyncCommand OnToTerminationOfUsePageButton => new AsyncCommand(async () =>
{
var navigationParameters = new NavigationParameters();
SurveyContent surveyContent = await _surveyService.BuildSurveyContent(
SelectedItemQ1.Value,
SelectedItemQ2.Value,
Q3Answer,
IsExposureDataProvision);

var navigationParameters = TerminationOfUsePage.BuildNavigationParams(surveyContent);
await NavigationService.NavigateAsync(nameof(TerminationOfUsePage), navigationParameters);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Acr.UserDialogs;
using Chino;
using Covid19Radar.Model;
using Covid19Radar.Repository;
using Covid19Radar.Resources;
using Covid19Radar.Services;
Expand All @@ -19,6 +20,9 @@ public class TerminationOfUsePageViewModel : ViewModelBase
{
private readonly ILoggerService _loggerService;
private readonly ILogFileService _logFileService;
private readonly ISurveyService _surveyService;
private readonly IDialogService _dialogService;

private readonly IUserDataRepository _userDataRepository;
private readonly IEventLogRepository _eventLogRepository;
private readonly ISendEventLogStateRepository _sendEventLogStateRepository;
Expand All @@ -29,10 +33,14 @@ public class TerminationOfUsePageViewModel : ViewModelBase
private readonly AbsExposureDetectionBackgroundService _absExposureDetectionBackgroundService;
private readonly AbsDataMaintainanceBackgroundService _absDataMaintainanceBackgroundService;

private SurveyContent _surveyContent = null;

public TerminationOfUsePageViewModel(
INavigationService navigationService,
ILoggerService loggerService,
ILogFileService logFileService,
ISurveyService surveyService,
IDialogService dialogService,
IUserDataRepository userDataRepository,
IEventLogRepository eventLogRepository,
ISendEventLogStateRepository sendEventLogStateRepository,
Expand All @@ -45,6 +53,9 @@ AbsDataMaintainanceBackgroundService absDataMaintainanceBackgroundService
{
_loggerService = loggerService;
_logFileService = logFileService;
_surveyService = surveyService;
_dialogService = dialogService;

_userDataRepository = userDataRepository;
_eventLogRepository = eventLogRepository;
_sendEventLogStateRepository = sendEventLogStateRepository;
Expand All @@ -56,11 +67,29 @@ AbsDataMaintainanceBackgroundService absDataMaintainanceBackgroundService
_absDataMaintainanceBackgroundService = absDataMaintainanceBackgroundService;
}

public override void Initialize(INavigationParameters parameters)
{
base.Initialize(parameters);

if (parameters.ContainsKey(TerminationOfUsePage.NavigationParameterNameSurveyContent))
{
_surveyContent = parameters.GetValue<SurveyContent>(TerminationOfUsePage.NavigationParameterNameSurveyContent);
}
}

public IAsyncCommand OnTerminationButton => new AsyncCommand(async () =>
{
UserDialogs.Instance.ShowLoading(AppResources.LoadingTextDeleting);

try
{
UserDialogs.Instance.ShowLoading(AppResources.LoadingTextDeleting);
// Submit survey content if needed
if (_surveyContent != null && !await _surveyService.SubmitSurvey(_surveyContent))
{
await _dialogService.ShowNetworkConnectionErrorAsync();
_loggerService.Error("Failed submit survey");
return;
}

// Stop exposure notifications
await StopExposureNotificationAsync();
Expand All @@ -84,16 +113,18 @@ AbsDataMaintainanceBackgroundService absDataMaintainanceBackgroundService
await _eventLogRepository.RemoveAllAsync();

_ = _logFileService.DeleteLogsDir();

UserDialogs.Instance.HideLoading();

// Navigate to complete page
await NavigationService.NavigateAsync($"/{nameof(TerminationOfUseCompletePage)}");
}
catch (Exception ex)
{
_loggerService.Exception("Failed termination of use", ex);
}
finally
{
UserDialogs.Instance.HideLoading();
}

// Navigate to complete page
await NavigationService.NavigateAsync($"/{nameof(TerminationOfUseCompletePage)}");
});

private async Task StopExposureNotificationAsync()
Expand Down
Loading