From 98d8e987488c2977e5fd058016f7dc669c913e47 Mon Sep 17 00:00:00 2001 From: ARIYAMA Keiji Date: Sat, 11 Jun 2022 22:52:42 +0900 Subject: [PATCH 1/5] Handle COCOA's `exposure_data.json`. --- src/components/ExposeChecker.vue | 162 +++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 18 deletions(-) diff --git a/src/components/ExposeChecker.vue b/src/components/ExposeChecker.vue index 5dd8b05..1808aba 100644 --- a/src/components/ExposeChecker.vue +++ b/src/components/ExposeChecker.vue @@ -120,7 +120,13 @@

- 結果:
{{resultText}}

+ 結果:
{{resultText}}
+

    +
  • + {{ exposureDict[date]["local_date"] }} +
  • +
+


本結果に関して:
@@ -222,6 +228,35 @@ import FAQ from './FAQ'; import COCOA2Dialog from './Cocoa2Dialog'; + function createExposureWindowKey(exposureWindow){ + return [ + exposureWindow["DateMillisSinceEpoch"], + ].join("-") + } + + function createExposureStatistics(exposureWindows){ + let exposureWindowDict = {} + + exposureWindows.forEach(ew => { + let key = createExposureWindowKey(ew) + let exposureWindowList + if (key in exposureWindowDict) { + exposureWindowList = exposureWindowDict[key] + } else { + exposureWindowList = [] + } + + exposureWindowList.push(ew) + exposureWindowDict[key] = exposureWindowList + }); + + return exposureWindowDict + } + + function dateToString(dateTimeUtc){ + return `${dateTimeUtc.getFullYear()}年${dateTimeUtc.getMonth() + 1}月${dateTimeUtc.getDate()}日` + } + export default { name: 'ExposeChecker', components: { @@ -230,21 +265,63 @@ }, methods:{ checkJson: function(){ - function checkCOCOA2iOS(matchedExposures){ - let result = false - matchedExposures.flatMap( checkItem => checkItem.Files.forEach( file => { - if (!('MatchCount' in file)){ result = true } - })) - return result - } + function checkCOCOALog(exposureData){ + let exposureDict = createExposureStatistics(exposureData["exposure_windows"]) - this.$gtag.event("checkJson") + const explainTextZeroContact = "説明:
本結果はCOCOA上の新規陽性登録者との接触検知のみが対象です。無症状感染者やCOCOAの陽性登録をしていない感染者の方が近くにいた可能性はありますので、引き続き感染症対策に万全を期すことをおすすめします。" + const explainTextNonZeroContact = "説明:
接触通知アプリ(COCOA)を開いて陽性者との接触の検出がない場合は感染リスクは低いものと推測されます。過度に恐れず、引き続き感染症対策に万全を期すことをおすすめします。" - const explainTextZeroContact = "説明:
本結果はCOCOA上の新規陽性登録者との接触検知のみが対象です。無症状感染者やCOCOAの陽性登録をしていない感染者の方が近くにいた可能性はありますので、引き続き感染症対策に万全を期すことをおすすめします。" - const explainTextNonZeroContact = "説明:
接触通知アプリ(COCOA)を開いて陽性者との接触の検出がない場合は感染リスクは低いものと推測されます。過度に恐れず、引き続き感染症対策に万全を期すことをおすすめします。" + let result = { + "text": null, + "explain": null, + "detail": null, + "detailText": null, + } + + let count = Object.keys(exposureDict).length + if (count === 0) { + result["text"] = "新規陽性登録者が近くにいた記録はありませんでした。" + result["explain"] = explainTextZeroContact + } else { + result["text"] = "新規陽性登録者が近くにいた記録が確認されました。" + result["explain"] = explainTextNonZeroContact + + let detail = {}; + Object.keys(exposureDict).map(dateMillsSinceEpoch => { + const exposrueWindows = exposureDict[dateMillsSinceEpoch]; + + let dateTimeUtc = new Date(0); + dateTimeUtc.setUTCMilliseconds(dateMillsSinceEpoch); + let localDate = dateToString(dateTimeUtc) + detail[dateMillsSinceEpoch] = { + "local_date": localDate, + "exposrue_windows": exposrueWindows, + } + }); + + result["detail"] = detail + result["detailText"] = JSON.stringify( + Object.keys(detail) + .map(dateMillsSinceEpoch => detail[dateMillsSinceEpoch]), + null, + 2 + ) + } + + return result; + } + function checkLegacyLog(exposeData){ + function checkCOCOA2iOS(matchedExposures){ + let result = false + matchedExposures.flatMap( checkItem => checkItem.Files.forEach( file => { + if (!('MatchCount' in file)){ result = true } + })) + return result + } + + const explainTextZeroContact = "説明:
本結果はCOCOA上の新規陽性登録者との接触検知のみが対象です。無症状感染者やCOCOAの陽性登録をしていない感染者の方が近くにいた可能性はありますので、引き続き感染症対策に万全を期すことをおすすめします。" + const explainTextNonZeroContact = "説明:
接触通知アプリ(COCOA)を開いて陽性者との接触の検出がない場合は感染リスクは低いものと推測されます。過度に恐れず、引き続き感染症対策に万全を期すことをおすすめします。" - try { - const exposeData = JSON.parse(this.exposeJsonText) let matchedExposures if ("ExposureChecks" in exposeData) { // iOS @@ -283,17 +360,64 @@ }) } + let result = { + "text": null, + "explain": null, + "detail": null, + "detailText": null, + } + if (matchedExposures.length === 0) { - this.resultText = "新規陽性登録者が近くにいた記録はありませんでした。" - this.explainText = explainTextZeroContact + result["text"] = "新規陽性登録者が近くにいた記録はありませんでした。" + result["explain"] = explainTextZeroContact + result["detailText"] = "" } else { - this.resultText = `${matchedExposures.length}件の新規陽性登録者が近くにいた記録が確認されました。` - this.resultJsonText = matchedExposures.map(e => JSON.stringify(e,null,2)).join("\n") - this.explainText = explainTextNonZeroContact + result["text"] = `${matchedExposures.length}件の新規陽性登録者が近くにいた記録が確認されました。` + result["explain"] = explainTextNonZeroContact + result["detailText"] = matchedExposures.map(e => JSON.stringify(e,null,2)).join("\n") } + + return result + } + + this.$gtag.event("checkJson") + + try { + const exposeData = JSON.parse(this.exposeJsonText) + + const fromDate = new Date() + fromDate.setDate(fromDate.getDate() - 14) + const fromEpochMillis = fromDate.getTime() + + let checkLogResult + + if ("exposure_windows" in exposeData) { + checkLogResult = checkCOCOALog(exposeData) + } else if ("ExposureChecks" in exposeData || Array.isArray(exposeData)) { + checkLogResult = checkLegacyLog(exposeData) + } else { + alert("ログのフォーマットが異なります") + return + } + + this.resultText = checkLogResult["text"] + this.explainText = checkLogResult["explain"] + this.resultJsonText = checkLogResult["detailText"] + + if (checkLogResult["detail"]) { + this.exposureDateList = Object.keys(checkLogResult["detail"]) + .filter(epochMillis => epochMillis >= fromEpochMillis) + .reverse() + this.exposureDict = checkLogResult["detail"] + } else { + this.exposureDateList = [] + this.exposureDict = {} + } + } catch (error) { alert("データフォーマットエラー"); } + }, clearJson: function(){ this.exposeJsonText = "" @@ -311,6 +435,8 @@ resultText: "", exposeJsonText: "", explainText: "", + exposureDateList: {}, + exposureDict: {}, panel:[], } }, From 74a533ff3859a589c6c3145437d5361be903fb0a Mon Sep 17 00:00:00 2001 From: ARIYAMA Keiji Date: Sat, 11 Jun 2022 23:08:14 +0900 Subject: [PATCH 2/5] Fix sort. --- src/components/ExposeChecker.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ExposeChecker.vue b/src/components/ExposeChecker.vue index 1808aba..e62087e 100644 --- a/src/components/ExposeChecker.vue +++ b/src/components/ExposeChecker.vue @@ -407,7 +407,7 @@ if (checkLogResult["detail"]) { this.exposureDateList = Object.keys(checkLogResult["detail"]) .filter(epochMillis => epochMillis >= fromEpochMillis) - .reverse() + .sort((a, b) => b - a) // Descending order this.exposureDict = checkLogResult["detail"] } else { this.exposureDateList = [] From 70c2ccb0109aba7f874fecf664e334202b629aae Mon Sep 17 00:00:00 2001 From: ARIYAMA Keiji Date: Sun, 12 Jun 2022 02:20:07 +0900 Subject: [PATCH 3/5] Remove inappropriate function. --- src/components/ExposeChecker.vue | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/ExposeChecker.vue b/src/components/ExposeChecker.vue index e62087e..5b5e447 100644 --- a/src/components/ExposeChecker.vue +++ b/src/components/ExposeChecker.vue @@ -228,17 +228,11 @@ import FAQ from './FAQ'; import COCOA2Dialog from './Cocoa2Dialog'; - function createExposureWindowKey(exposureWindow){ - return [ - exposureWindow["DateMillisSinceEpoch"], - ].join("-") - } - function createExposureStatistics(exposureWindows){ let exposureWindowDict = {} exposureWindows.forEach(ew => { - let key = createExposureWindowKey(ew) + let key = ew["DateMillisSinceEpoch"] let exposureWindowList if (key in exposureWindowDict) { exposureWindowList = exposureWindowDict[key] From d982c66807f58f6a1c278e5f580fc2f08639c06d Mon Sep 17 00:00:00 2001 From: ARIYAMA Keiji Date: Sun, 12 Jun 2022 13:05:11 +0900 Subject: [PATCH 4/5] Fix code style and refactoring. --- src/components/ExposeChecker.vue | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/ExposeChecker.vue b/src/components/ExposeChecker.vue index 5b5e447..f284102 100644 --- a/src/components/ExposeChecker.vue +++ b/src/components/ExposeChecker.vue @@ -234,7 +234,7 @@ exposureWindows.forEach(ew => { let key = ew["DateMillisSinceEpoch"] let exposureWindowList - if (key in exposureWindowDict) { + if (key in exposureWindowDict) { exposureWindowList = exposureWindowDict[key] } else { exposureWindowList = [] @@ -242,7 +242,7 @@ exposureWindowList.push(ew) exposureWindowDict[key] = exposureWindowList - }); + }) return exposureWindowDict } @@ -272,8 +272,7 @@ "detailText": null, } - let count = Object.keys(exposureDict).length - if (count === 0) { + if (Object.keys(exposureDict).length === 0) { result["text"] = "新規陽性登録者が近くにいた記録はありませんでした。" result["explain"] = explainTextZeroContact } else { @@ -282,16 +281,16 @@ let detail = {}; Object.keys(exposureDict).map(dateMillsSinceEpoch => { - const exposrueWindows = exposureDict[dateMillsSinceEpoch]; + const exposrueWindows = exposureDict[dateMillsSinceEpoch] - let dateTimeUtc = new Date(0); - dateTimeUtc.setUTCMilliseconds(dateMillsSinceEpoch); + let dateTimeUtc = new Date(0) + dateTimeUtc.setUTCMilliseconds(dateMillsSinceEpoch) let localDate = dateToString(dateTimeUtc) detail[dateMillsSinceEpoch] = { "local_date": localDate, "exposrue_windows": exposrueWindows, } - }); + }) result["detail"] = detail result["detailText"] = JSON.stringify( From 0587205af43f74eaf7e11c152bb20b449206713d Mon Sep 17 00:00:00 2001 From: ARIYAMA Keiji Date: Sun, 12 Jun 2022 13:07:42 +0900 Subject: [PATCH 5/5] Fix code style. --- src/components/ExposeChecker.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ExposeChecker.vue b/src/components/ExposeChecker.vue index f284102..d3d5f17 100644 --- a/src/components/ExposeChecker.vue +++ b/src/components/ExposeChecker.vue @@ -279,7 +279,7 @@ result["text"] = "新規陽性登録者が近くにいた記録が確認されました。" result["explain"] = explainTextNonZeroContact - let detail = {}; + let detail = {} Object.keys(exposureDict).map(dateMillsSinceEpoch => { const exposrueWindows = exposureDict[dateMillsSinceEpoch] @@ -301,7 +301,7 @@ ) } - return result; + return result } function checkLegacyLog(exposeData){ function checkCOCOA2iOS(matchedExposures){