# Scoring

## Scoring <a href="#scoring" id="scoring"></a>

You can get the average and maximum aggregate scores for previous trips taken by using the `ScoringAggregateService`. Functions have been added to query the scores over various different time periods. The time periods available are:

* today
* the last 7 days / last week
* the last 30 days / last month
* the last 90 days
* the last 365 days
* the last N days
* custom date range

The definition of a day is based on the user's current timezone.

For the following, the example timezone should be considered to be UTC-0400 (i.e Toronto). If a request for today's data is made at on the 2nd day of the month, at 23:00 (11PM) UTC-0400, the result should be based on that specific day, even though the current date according to the UTC would be the 3rd day of the month. (11:00PM UTC-0400 corresponds to 03:00AM the next day on UTC-0000 time).

Some other examples: User's time: 2020-01-01 - 00:01AM UTC-0400 (04:01AM UTC-0000) Results: 2020-01-01

User's time: 2020-01-01 - 12:01PM UTC-0400 (04:01PM UTC-0000) Results: 2020-01-01

User's time: 2020-01-01 - 10:01PM UTC-0400 (2020-01-02 02:01AM UTC-0000) Results: 2020-01-01

## Scoring Aggregate <a href="#scoring-aggregate" id="scoring-aggregate"></a>

An aggregate of scoring averages and sub scoring (braking, cornering, acceleration and speed).

Any valid user on the DriveSync system (identified via the `Identity`set during [SDK initialization](/readme/ios/initializing-the-sdk.md#identity)) should be able to know scoring aggregate.

### ScoringAggregate model <a href="#scoringaggregate-model" id="scoringaggregate-model"></a>

ScoringAggregate model includes scores data along with the events captured in `ScoringAggregate.tripScoringDailyAggregate.componentScores`.

The host app can access the events through `componentScores` which have score types:

* speeding
* milage
* braking
* cornering
* payd
* overSpeeding
* acceleration
* distractedDriving

The `otherSubScores` is type of Dictionary for which the key is a custom event that is not in the above list.

### **Pre-made date ranges** <a href="#pre-made-date-ranges" id="pre-made-date-ranges"></a>

There are some Pre-made requests for easy access to some commonly used date ranges, as they are commonly used for other scoring components.

The current list includes:

* Today
* Last 7 days
* Last 30 days
* Last 90 days
* Last 365 days

**Today**

To fetch the `ScoringAggregate` for the user for the today, the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.today(then: { result in
    guard !result.value.isEmpty else {
        // failure
        return
    }
    completionHandler(.success(result.value))
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchTodaysDailyScores() { result: Result<Content?>? ->
    if (result?.value == null || result.throwable != null) {
        // failure
    } else {
        // Success
        val content = result.value
    }
})
```

{% endtab %}
{% endtabs %}

**Last 7 days**

Fetch the `ScoringAggregate` for the user for the last 7 days, the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.last7Days(then: { result in
    guard !result.value.isEmpty else {
        // failure
        return
    }
    completionHandler(.success(result.value))
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchLast7DaysDailyScores() { result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

**Other values**

In order to get last 30, 90, and 365 days simply replace number "7" with the desired value respectively.

### **Custom date range** <a href="#custom-date-range" id="custom-date-range"></a>

Fetching data for the scoring aggregate requires a start and end date (range).

The date is assumed to be based on the user's current timezone. As an example, if the current user's timezone is set to UTC-5:00, the long 1603416046000 corresponds to 2020-10-22 (even though it corresponds to 2020-10-23 1:20AM UTC).

To fetch the `ScoringAggregate` for the user over a period of time with a start and end date(range), the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.dateRange(from: Date(), to: Date(), then: { result in
    guard !result.value.isEmpty else {
        // failure
        return
    }
    completionHandler(.success(result.value))
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchDaily(from, to) { result: Result<Content?>? ->
    if (result?.value == null || result.throwable != null) {
        // failure
    } else {
        // Success
        val content = result.value
    }
})
```

{% endtab %}
{% endtabs %}

### **Vehicle** <a href="#vehicle" id="vehicle"></a>

Fetching data for the scoring aggregate requires a start and end date (range).

**Required information**

\*vehicle ID: In order to fetch scoring data for a vehicle, the application must have a valid vehicle associated with the identity.

To fetch the `ScoringAggregate` for a vehicle of the user over a period of time with a start and end date(range), the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
service.fetchAggregateScoresByVehicle(vehicleId: vehicleId, from: Date(), to: Date(), then: { result in
    guard !result.value.isEmpty else {
        // failure
        return
    }
    completionHandler(.success(result.value))
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchAggregateScoresByVehicle(vehicleID, from, to) {
     result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

To fetch the `ScoringAggregate` for a vehicle of the user for the past N days, the following API can be used.

{% tabs %}
{% tab title="Swift" %}

```swift
service.fetchLastNDaysAggregateScoresByVehicle(vehicleId: vehicleId, days: days, then: { result in
    guard !result.value.isEmpty else {
        // failure
        return
    }
    completionHandler(.success(result.value))
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchLastNDaysAggregateScoresByVehicle(vehicleID, days) {
     result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

**Failures**

ScoringService provides a \[Throwable] in the results sent to the \[ResultCallback].

The \[Result] provided can be differentiated by checking the type of results, which is always \[Result.Success] or \[Result.Failure].

Alternatively, the \[ResultCallback] can test for the presence of the throwable.

```kotlin
scoringService.fetchTodaysScores(result -> {
   ScoringAggregate aggregate = result.getValue();
   if (aggregate != null) {
       setScoreTextValue("Daily: ", result.getValue());
   } else {
       NetworkException exception = (NetworkException) result.getThrowable();
       if (exception.getReason() == NetworkException.Reason.SERVER_NOT_FOUND) {
           showError("Server not found");
       }
   }
});
```

## Scoring average <a href="#scoring-average" id="scoring-average"></a>

Any valid user on the DriveSync system (identified via the Identity set during [SDK initialization](/readme/ios/initializing-the-sdk.md#identity)) should be able to know scoring aggregate.

### ScoringAverage model <a href="#scoringaverage-model" id="scoringaverage-model"></a>

ScoringAverage model includes scores data along with the events captured in `ScoringAverage.tripScoringAverage.componentScores`.

The host app can access the events through `componentScores` which accepts custom scoring events with the sub component named `otherSubScores`.

The `otherSubScores` is type of Dictionary for which the key is a custom event required for host app.

In all the above API's "Daily" can replaced by "Average" to get the corresponding response.

**Concrete example**

For example to fetch the `ScoringAverage` for the user for the last 7 days, the following API can be used.

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.custom(from: fromDate, to: toDate, then: { result in
    guard !result.value.isEmpty else {
        // error
        return
    }
    completionHandler(.success(result.value))
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchLast7DaysAverageScores() { result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

### Weekly average <a href="#weekly-average" id="weekly-average"></a>

To receive week by week score data, call fetchWeek api to recieve the desired data. The number passed as argument is a UInt representing the number of weeks you want the data. For example, to retreive current week you'll pass 0 and for last week you need to pass 1.

For example to fetch the `ScoringAverage` for the user for the desired week, the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.fetchWeek(weekNumber: weekNumber, then: { result in
    guard !result.value.isEmpty else {
        // error
        return
    }
    completionHandler(.success(result.value))
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchWeek(weekNumber) { result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

### **Vehicle** <a href="#vehicle-1" id="vehicle-1"></a>

Fetching data for the scoring average requires a start and end date (range).

**Required information**

\*vehicle ID: In order to fetch scoring data for a vehicle, the application must have a valid vehicle associated with the identity.

To fetch the `ScoringAverage` for a vehicle of the user over a period of time with a start and end date(range), the following API can be used.

**Concrete example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.fetchAverageScoresByVehicle(vehicleId: vehicleId, from: fromDate, to: toDate, then: { result in
    guard !result.value.isEmpty else {
        // error
        return
    }
    completionHandler(.success(result.value))
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchAverageScoresByVehicle(vehicleID, from, to) {
     result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

To fetch the `ScoringAverage` for a vehicle of the user for the past N days, the following can be used.

*Note: In iOS (Swift) the method* **fetchLastNDaysAverageScores**, *has vehicle ID as optional. If it is NOT passed, the api returns user's last N days average scores.*

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()
service.fetchLastNDaysAverageScores(vehicleId: vehicleId, days: days, then: { result in
    guard !result.value.isEmpty else {
        // error
        return
    }
    completionHandler(.success(result.value))
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchLastNDaysAverageScoresByVehicle(vehicleID, days) {
     result: Result<Content?>? ->
        if (result?.value == null || result.throwable != null) {
            // failure
        } else {
            // Success
            val content = result.value
        }
})
```

{% endtab %}
{% endtabs %}

### PolicyScoring

**Fetch Average Scores For User By Policy (Using Start & End Date)**

To fetch average scores for a specifc user and policy within the given start and end date, the following API can be used.

#### Parameters:

* **`userId`**: The user ID
* **`policyId`**: The policy ID
* **`startDate`**: Start date (optional)
* **`endDate`**: End date (optional)
* **`verificationCutOffDate`**: Verification cutoff date (optional)

#### **Example**

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()

service.fetchAverageScoresByPolicy(userId: userId,
                                   policyId: policyId,
                                   startDate: startDate,
                                   endDate: endDate,
                                   verificationCutOffDate: cutOffDate,
                                   then: { result in
    switch result {
    case .success(let policyScoring):
        // fetch successfull
    case .failure:
        // API call failed
    }
})
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchAverageScoresByPolicy(userId,
                                    policyId,
                                    startDate,
                                    endDate,
                                    verificationCutOffDate) { result: Result<UserPolicyScore>? ->
    if (result?.value == null || result.throwable != null) {
        // failure
    } else {
        // Success
        val userPolicyScore = result.value
    }
}
```

{% endtab %}
{% endtabs %}

**Fetch Average Scores For User By Policy (Using Week)**

To fetch average scores for a specifc user and policy within the given week, the following API can be used.

#### Parameters:

* `userId`: User id required
* `policyId`: Policy id required
* `userScoreWeek`: Week optional (Week number is relative to the current week (0 for current week, 1 for previous week))
* `verificationCutOffDate`: Verification cutoff date optional

{% tabs %}
{% tab title="Swift" %}

```swift
let service = ScoringService()

service.fetchAverageScoresByPolicy(userId: userId,
                                   policyId: policyId,
                                   userScoreWeek: weekNumber,
                                   verificationCutOffDate: cutOffDate,
                                   then: { result in
    switch result {
    case .success(let policyScoring):
        // fetch successfull
    case .failure:
        // API call failed
    }
})

```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val service = ScoringService()
service.fetchAverageScoresByPolicy(userId,
                                    policyId,
                                    userScoreWeek,
                                    verificationCutOffDate) { result: Result<PolicyScoring>? ->
    if (result?.value == null || result.throwable != null) {
        // API call failed
    } else {
        // fetch successful
        val policyScoring = result.value
    }
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sdk.ims.tech/drivesync-portal/scoring.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
