[Huawei Developers] muraliameakula:
The COVID-19 outbreak has thrown personal health into the spotlight. To help tackle the pandemic, HUAWEI Contact Shield tracks contact records between people.

This article explains how the risk value used to determine a person's risk of catching COVID-19 is calculated.

For details about how Contact Shield tracks contact records, please refer to the development guide.

Due to version updates, Contact Shield provides two logic sets (TotalRiskValue and ContactWindowScore) for you to calculate the risk value. Let's learn about TotalRiskValue and ContactWindowScore respectively.

TotalRiskValue

Contact Shield calculates the total risk value based on the following formula:

TotalRiskValue = attenuationRiskValue * daysAfterContactedRiskValue * durationRiskValue * initialRiskLevelRiskValue

attenuationRiskValue: contact distance with a diagnosed user. The closer the distance is, the higher the risk value is. The value ranges from 0 to 8.

daysAfterContactedRiskValue: number of days between the last contact time and the current time. The closer the value is to the current time, the higher the risk value is. The value ranges from 0 to 8.

durationRiskValue: risk value corresponding to the contact duration. The longer the contact duration is, the higher the risk value is. The value ranges from 0 to 8.

initialRiskLevelRiskValue: initial risk level of the current periodic key, which is determined when the diagnosed user uploads the periodic key. The value ranges from 0 to 8.

TotalRiskValue is obtained by multiplying these four variables. For details about how to calculate these four variables, please refer to the following code:

The putSharekeyFiles API is called before the diagnosis result is obtained (getContactSketch and getContactDetail). This API contains an input parameter DiagnosisConfiguration, which determines the four variables mentioned above.

public void putKeys () {
........
// Set the diagnosis configuration.
DiagnosisConfiguration config = new DiagnosisConfiguration.Builder()
.setAttenuationDurationThresholds(100, 200)
.setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setMinimumRiskValueThreshold(2)
.build();
PendingIntent pendingIntent = PendingIntent.getService(this, 0,
new Intent(this, BackgroundContackCheckingIntentService.class),
PendingIntent.FLAG_UPDATE_CURRENT);
// Start diagnosis.
mEngine.putSharedKeyFiles(pendingIntent, putList, config, token)
.addOnSuccessListener(aVoid -> {
Log.d(TAG, "putSharedKeyFiles succeeded.");
})
.addOnFailureListener(e -> {
Log.d(TAG, "putSharedKeyFiles failed, cause: " + e.getMessage());
});
}

We can learn about the four variables and their value setting logic in DiagnosisConfiguration based on the API reference. We can see that, the four variables are set as arrays in the DiagnosisConfiguration class.

Although the arrays here are size-mutable arrays (int...), their lengths are actually fixed. The following examples give a clearer insight into the four variables.

The description of arrays in the setAttenuationRiskValues method in the API reference is as follows:

Contact Shield roughly defines the contact distance between two people based on the attenuation of the Bluetooth signal.

For example, setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:

If the attenuation is greater than 73 dBm, the value of attenuationRiskValues is 0.

If the attenuation is greater than 63 dBm and less than or equal to 73 dBm, the value of attenuationRiskValues is 0.

If the attenuation is greater than 51 dBm and less than or equal to 63 dBm, the value of attenuationRiskValues is 0.

If the attenuation is greater than 33 dBm and less than or equal to 51 dBm, the value of attenuationRiskValues is 0.

If the attenuation is greater than 27 dBm and less than or equal to 33 dBm, the value of attenuationRiskValues is 1.

If the attenuation is greater than 15 dBm and less than or equal to 27 dBm, the value of attenuationRiskValues is 2.

If the attenuation is greater than 10 dBm and less than or equal to 15 dBm, the value of attenuationRiskValues is 3.

If the attenuation is less than or equal to 10 dBm, the value of attenuationRiskValues is 4.

The configurations of daysAfterContactedRiskValues, durationRiskValues and initialRiskLevelRiskValues are similar.

setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 14, the value of daysAfterContactedRiskValues is 0.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 12 and less than 14, the value of daysAfterContactedRiskValues is 0.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 10 and less than 12, the value of daysAfterContactedRiskValues is 0.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 8 and less than 10, the value of daysAfterContactedRiskValues is 0.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 6 and less than 8, the value of daysAfterContactedRiskValues is 1.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 4 and less than 6, the value of daysAfterContactedRiskValues is 2.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 2 and less than 4, the value of daysAfterContactedRiskValues is 3.

If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 0 and less than 2, the value of daysAfterContactedRiskValues is 4.

setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:

If there is no contact between a person and a diagnosed user, the value of durationRiskValues is 0.

If the contact duration between a person and a diagnosed user is less than or equal to 5 minutes, the value of durationRiskValues is 0.

If the contact duration between a person and a diagnosed user is greater than 5 and less than or equal to 10 minutes, the value of durationRiskValues is 0.

If the contact duration between a person and a diagnosed user is greater than 10 and less than or equal to 15 minutes, the value of durationRiskValues is 0.

If the contact duration between a person and a diagnosed user is greater than 15 and less than or equal to 20 minutes, the value of durationRiskValues is 1.

If the contact duration between a person and a diagnosed user is greater than 20 and less than or equal to 25 minutes, the value of durationRiskValues is 2.

If the contact duration between a person and a diagnosed user is greater than 25 and less than or equal to 30 minutes, the value of durationRiskValues is 3.

If the contact duration between a person and a diagnosed user is greater than 30 minutes, the value of durationRiskValues is 4.

setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:

If a user has had contacted with a diagnosed user who has the lowest risk level, the value of initialRiskLevelRiskValues is 0.

If a user has had contacted with a diagnosed user who has the low risk level, the value of initialRiskLevelRiskValues is 0.

If a user has had contacted with a diagnosed user who has the low-medium risk level, the value of initialRiskLevelRiskValues is 0.

If a user has had contacted with a diagnosed user who has the medium risk level, the value of initialRiskLevelRiskValues is 0.

If a user has had contacted with a diagnosed user who has the medium-high risk level, the value of initialRiskLevelRiskValues is 1.

If a user has had contacted with a diagnosed user who has the high risk level, the value of initialRiskLevelRiskValues is 2.

If a user has had contacted with a diagnosed user who has the extremely high risk level, the value of initialRiskLevelRiskValues is 3.

If a user has had contacted with a diagnosed user who has the highest risk level, the value of initialRiskLevelRiskValues is 4.

Note: You can manually set the risk level after obtaining the shared key of the diagnosed user. For details, please refer to setInitialRiskLevel.

The above is the value setting logic of attenuationRiskValue, daysAfterContactedRiskValue, durationRiskValue, and initialRiskLevelRiskValue. You can view these four variables in the ContactDetail class that is returned by calling the getContactDetail API after diagnosis.

And that’s everything for calculating TotalRiskValue.

This example will help illustrate the logic:

On March 10, 2020, A and B had a meal together (the Bluetooth attenuation was about 10–15), for around 40 minutes. After the meal, they both returned to their homes and never saw each other again.

On March 15, 2020, B was diagnosed with COVID-19 and labeled as medium-high risk. Following this, healthcare workers immediately instructed B to upload his shared key onto Contact Shield. If the diagnosis configuration code of the app used by the hospital is as follows:

DiagnosisConfiguration config = new DiagnosisConfiguration.Builder() .setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4) …… .build();

what is the value of TotalRiskValue for A?

This is calculated as follows:

According to the description, the Bluetooth attenuation ranges from 10 to 15. Therefore, the value of attenuationRiskValue is 3 based on the diagnosis configuration setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4).

The contact duration between the two is 40 minutes, meaning the value of durationRiskValue is 4 based on the diagnosis configuration setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4).

Five days have elapsed since A and B contact. As a result, the value of daysAfterContactedRiskValue is 2 based on the diagnosis configuration setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4).

B is diagnosed as a COVID-19 patient with medium-high risk, and therefore the value of initialRiskLevelRiskValue is 1 based on the diagnosis configuration setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4).

As a result, TotalRiskValue = attenuationRiskValue * daysAfterContactedRiskValue * durationRiskValue * initialRiskLevelRiskValue = 3 x 2 x 4 x 1 = 24.

If the above assumption remains unchanged, while the diagnosis configuration code is changed to the following:

DiagnosisConfiguration config = new DiagnosisConfiguration.Builder()
.setAttenuationRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setDaysAfterContactedRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setDurationRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setInitialRiskLevelRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
……
.build();

TotalRiskValue of A will change to 1680 (7 x 6 x 8 x 5 = 1680). The calculation details are not described here.

ContactWindowScore

Contact Shield calculates the risk value of each contact window based on the following formula:

ContactWindowScore = reportTypeScore * contagiousnessScore * attenuationDurationScore

reportTypeScore: risk value corresponding to the report type of the shared key. For details about its configuration, please refer to setWeightOfReportType().

contagiousnessScore: risk value corresponding to the contagiousness of the diagnosed user. For details about its configuration, please refer to setWeightOfContagiousness(). Contagiousness is related to the number of days between the current day and the first symptom of the virus. For details, please refer to setDaysSinceCreationToContagiousness().

attenuationDurationScore: Bluetooth scanning data contained in the contact window, and risk value calculated based on the contact distance and time. For details about the configuration, please refer to setThresholdsOfAttenuationInDb().

At the code level, ContactWindowScore and TotalRiskValue are configured at different time points.

Specifically, TotalRiskValue is configured before you call the putSharekeyFiles API, while ContactWindowScore is configured when you call the getDailySketch API after the putSharekeyFiles API is successfully called. The sample code is as follows:

public void getDailySketches() {
DailySketchConfiguration configuration = new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)
.setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))
.setThresholdOfDaysSinceHit(0)
.setMinWindowScore(0)
.build();

mEngine.getDailySketch(configuration)
.addOnSuccessListener(dailySketches -> {
Log.d(TAG, "getDailySketch succeeded.");
// Process diagnosis results.
………
})
.addOnFailureListener(e -> Log.d(TAG, "getDailySketch failed." + e.toString()));
}

Unlike DiagnosisConfiguration, which configures TotalRiskValue mainly in the form of array, DailySketchConfiguration configures ContactWindowScore in the form of chain expression.

Note: The above sample code can be called only after the putSharekeyFiles API is successfully called.

We can learn about the three variables (reportType, contagiousnessScore, and attenuationDurationScore) and how their values are set based on the API reference.

The value of reportTypeScore is related to the setWeightOfReportType API which is in the form of <key, value> and can be called repeatedly. key indicates the current report type, and value indicates the weight of each report type.

ReportType values displayed in the following figure are for reference only, and their values can be customized as required.

If setWeightOfReportType() is set as follows:

new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)

it indicates:

If reportType is 0, the value of reportTypeScore is 0.

If reportType is 1, the value of reportTypeScore is 1.0.

If reportType is 2, the value of reportTypeScore is 1.1.

If reportType is 3, the value of reportTypeScore is 1.2.

If reportType is 4, the value of reportTypeScore is 1.3.

If reportType is 5, the value of reportTypeScore is 1.4.

The configurations of contagiousnessScore and attenuationDurationScore are similar.

The value of contagiousnessScore is related to the setWeightOfContagiousness API which is in the form of <key, value> and can be called repeatedly. key indicates the contagiousness of the current confirmed patient, and value indicates the weight of each contagiousness.

Contagiousness values displayed in the following figure are for reference only.

If setWeightOfContagiousness() is set as follows:

new DailySketchConfiguration.Builder()
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)

If the diagnosed user has no or uncertain contagiousness, Contagiousness is 0 and the value of contagiousnessScore is 0.

If the diagnosed user has standard contagiousness, Contagiousness is 1 and the value of contagiousnessScore is 2.1.

If the diagnosed user has high contagiousness, Contagiousness is 2 and the value of contagiousnessScore is 2.2.

The value of attenuationDurationScore is related to the setThresholdsOfAttenuationInDb API which has two input parameters: List<Integer> list and List<Double> list1. For details, please refer to the description in the API reference.

If setThresholdsOfAttenuationInDb() is set as follows:

setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))

it indicates: If the Bluetooth signal strength is less than or equal to 50 dBm, the value of attenuationDurationScore is 2.5.

If the Bluetooth signal strength is greater than 50 dBm and less than or equal to 150 dBm, the value of attenuationDurationScore is 2.0.

If the Bluetooth signal strength is greater than 150 dBm and less than or equal to 200 dBm, the value of attenuationDurationScore is 1.0.

If the Bluetooth signal strength is greater than 200 dBm, the value of attenuationDurationScore is 0.

This part has shown the value setting logic of reportTypeScore, contagiousnessScore, and attenuationDurationScore.

Note: You can view these three variables in the ContactWindow class that is returned by calling the getContactWindow API after diagnosis.

And that’s everything for calculating ContactWindowScore.

This example will help illustrate the logic:

On March 10, 2020, A and B had a meal together (the Bluetooth attenuation was about 10–15), for around 40 minutes. After the meal, they both returned to their homes and never saw each other again.

On March 15, 2020, B was diagnosed with COVID-19 and labeled as high contagiousness. Following this, healthcare workers immediately instructed B to upload his shared key onto Contact Shield, and set his reportType to 1. If the diagnosis configuration code of the app used by the hospital is as follows:

DailySketchConfiguration configuration = new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)
.setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))
.setThresholdOfDaysSinceHit(0)
.setMinWindowScore(0)
.build();

what is the value of TotalRiskValue for A?

This is calculated as follows:

The Bluetooth attenuation ranges from 10 to 15. Therefore, the value of attenuationDurationScore is 2.5 based on the diagnosis configuration setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0)).

B is confirmed as a diagnosed patient with high contagiousness, and subsequently the value of contagiousnessScore is 2.2 based on the diagnosis configuration setWeightOfContagiousness(2, 2.2).

Healthcare workers set the reportType for B to 1. Therefore, the value of reportTypeScore is 1.0 based on the diagnosis configuration setWeightOfReportType(1, 1.0).

As a result, ContactWindowScore = reportTypeScore * contagiousnessScore * attenuationDurationScore = 1.0 x 2.2 x 2.5 = 5.5.

If the above configuration remains unchanged while B is determined to have standard contagiousness, and his reportType is set to 3,

TotalRiskValue of A will change to 6.3 (1.2 x 2.1 x 2.5 = 6.3). The calculation details are not described here.

To learn more, please visit:

HUAWEI Developers official website

Development Guide

Reddit to join developer discussions

GitHub or Gitee to download the demo and sample code

Stack Overflow to solve integration problems

Follow our official account for the latest HMS Core-related news and updates.

Original Source