Skip to content

Commit 5b96ea8

Browse files
authored
Merge pull request #688 from populus-ai/rate-applies-when
Add a rate_applies_when field to Policy Rules
2 parents 8f35ac8 + f38cc96 commit 5b96ea8

5 files changed

Lines changed: 187 additions & 12 deletions

File tree

policy/README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,9 @@ An individual `Rule` object is defined by the following fields:
281281
| `inclusive_maximum` | boolean | Optional | Whether the rule `maximum` is considered in-bounds (default `true`) |
282282
| `rate_amount` | integer | Optional | Amount of the rate (see [Rate Amounts](#rate-amounts)) |
283283
| `rate_recurrence` | enum | Optional | Recurrence of the rate (see [Rate Recurrences](#rate-recurrences)) |
284-
| `start_time` | ISO 8601 time `hh:mm:ss` | Optional | Beginning time-of-day when the rule is in effect (default 00:00:00). |
285-
| `end_time` | ISO 8601 time `hh:mm:ss` | Optional | Ending time-of-day when the rule is in effect (default 23:59:59). |
284+
| `rate_applies_when` | enum | Optional | Specifies when a rate is applied to a rule (see [Rate Applies When](#rate-applies-when)) (defaults to `out_of_bounds`) |
285+
| `start_time` | ISO 8601 time `hh:mm:ss` | Optional | Beginning time-of-day when the rule is in effect (default 00:00:00). |
286+
| `end_time` | ISO 8601 time `hh:mm:ss` | Optional | Ending time-of-day when the rule is in effect (default 23:59:59). |
286287
| `days` | day[] | Optional | Days `["sun", "mon", "tue", "wed", "thu", "fri", "sat"]` when the rule is in effect (default all) |
287288
| `messages` | `{ String:String }` | Optional | Message to rider user, if desired, in various languages, keyed by language tag (see [Messages](#messages)) |
288289
| `value_url` | URL | Optional | URL to an API endpoint that can provide dynamic information for the measured value (see [Value URL](#value-url)) |
@@ -342,7 +343,7 @@ The amount of a rate applied when this rule applies, if applicable (default zero
342343

343344
#### Rate Recurrences
344345

345-
Rate recurrences specify when a rate is applied – either once, or periodically according to a `time_unit` specified using [Rule Units](#rule-units). A `time_unit` refers to a unit of time as measured in local time for the jurisdiction – a day begins at midnight local time, an hour begins at the top of the hour, etc.
346+
Rate recurrences specify how a rate is applied – either once, or periodically according to a `time_unit` specified using [Rule Units](#rule-units). A `time_unit` refers to a unit of time as measured in local time for the jurisdiction – a day begins at midnight local time, an hour begins at the top of the hour, etc.
346347

347348
| Name | Description |
348349
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -353,6 +354,19 @@ Rate recurrences specify when a rate is applied – either once, or periodicall
353354

354355
[Top][toc]
355356

357+
#### Rate Applies When
358+
359+
The `rate_applies_when` field specifies when a rate should be applied to an event or count,
360+
e.g. is it when the event is within the Rule bounds or when it is outside?
361+
It defaults to `out_of_bounds`.
362+
363+
The `rate_applies_when` field may take the following values:
364+
365+
| Name | Description |
366+
| --------------- | ----------- |
367+
| `in_bounds` | Rate applies when an event or count is within the rule `minimum` and `maximum` |
368+
| `out_of_bounds` | Rate applies when an event or count is outside of the rule `minimum` and `maximum` |
369+
356370
### Messages
357371

358372
Some Policies as established by the Agency may benefit from rider communication. This optional field contains a map of languages to messages, to be shown to the user.

policy/examples/README.md

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ File: [`per-trip-fees.json`](per-trip-fees.json)
274274
"rule_type": "rate",
275275
"rule_units": "amount",
276276
"rate_amount": 25,
277-
"rate_recurrence": "once",
277+
"rate_recurrence": "once_on_match",
278278
"geographies": [
279279
"b4bcc213-4888-48ce-a33d-4dd6c3384bda"
280280
],
@@ -456,8 +456,19 @@ This policy states parking fees as such:
456456
- Parking every hour onwards costs $10
457457

458458
For example, say a vehicle is parked for 6.5 hours. It will be charged `$2 (0-1hr) + $4 (1-2hr) + $10 (2-3hr) + $10 (3-4hr) + $10 (4-5hr) + $10 (5-6hr) + $10 (6-6.5hr) = $56`
459+
460+
This policy may be specified different ways using the `rate_applies_when` field.
461+
Both examples are shown here.
462+
463+
### With default `rate_applies_when = "out_of_bounds"`
464+
465+
By default the `rate_applies_when` field has the value `out_of_bounds`,
466+
meaning the rate should take effect when an event is outside the bounds
467+
of a rule's `minimum` and `maximum` values.
468+
459469
File: [`tiered-parking-fees-per-hour.json`](tiered-parking-fees-per-hour.json)
460-
```
470+
471+
```json
461472
{
462473
"name": "Tiered Dwell Time Example",
463474
"description": "First hour $2, second hour $4, every hour onwards $10",
@@ -506,7 +517,76 @@ File: [`tiered-parking-fees-per-hour.json`](tiered-parking-fees-per-hour.json)
506517
"rate_recurrence": "each_time_unit"
507518
}
508519
]
509-
}
520+
}
521+
```
522+
523+
### With `rate_applies_when = "in_bounds"`
524+
525+
When the `rate_applies_when` field has the value `in_bounds`,
526+
the rate takes effect when an event is within a rule's `minimum` and
527+
`maximum` values. Note that this also uses the `inclusive_minimum` and
528+
`inclusive_maximum` fields to create non-overlapping ranges for the rules.
529+
530+
File: [`tiered-parking-fees-per-hour-in-bounds.json`](tiered-parking-fees-per-hour-in-bounds.json)
531+
532+
```json
533+
{
534+
"name": "Tiered Dwell Time Example",
535+
"description": "First hour $2, second hour $4, every hour onwards $10",
536+
"policy_id": "2800cd0a-7827-4110-9713-b9e5bf29e9a1",
537+
"start_date": 1558389669540,
538+
"publish_date": 1558389669540,
539+
"end_date": null,
540+
"prev_policies": null,
541+
"provider_ids": [],
542+
"currency": "USD",
543+
"rules": [
544+
{
545+
"name": "0-1 Hour",
546+
"rule_id": "6b6fe61b-dbe5-4367-8e35-84fb14d23c54",
547+
"rule_type": "time",
548+
"rule_units": "hours",
549+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
550+
"statuses": { "available": [], "non_operational": [] },
551+
"vehicle_types": ["bicycle", "scooter"],
552+
"maximum": 1,
553+
"inclusive_maximum": false,
554+
"rate_applies_when": "in_bounds",
555+
"rate_amount": 200,
556+
"rate_recurrence": "each_time_unit"
557+
},
558+
{
559+
"name": "1-2 Hours",
560+
"rule_id": "edd6a195-bb30-4eb5-a2cc-44e5a18798a2",
561+
"rule_type": "time",
562+
"rule_units": "hours",
563+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
564+
"statuses": { "available": [], "non_operational": [] },
565+
"vehicle_types": ["bicycle", "scooter"],
566+
"minimum": 1,
567+
"maximum": 2,
568+
"inclusive_minimum": true,
569+
"inclusive_maximum": false,
570+
"rate_applies_when": "in_bounds",
571+
"rate_amount": 400,
572+
"rate_recurrence": "each_time_unit"
573+
},
574+
{
575+
"name": "> 2 hours",
576+
"rule_id": "9cd1768c-ab9e-484c-93f8-72a7078aa7b9",
577+
"rule_type": "time",
578+
"rule_units": "hours",
579+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
580+
"statuses": { "available": [], "non_operational": [] },
581+
"vehicle_types": ["bicycle", "scooter"],
582+
"minimum": 2,
583+
"inclusive_minimum": true,
584+
"rate_applies_when": "in_bounds",
585+
"rate_amount": 1000,
586+
"rate_recurrence": "each_time_unit"
587+
}
588+
]
589+
}
510590
```
511591

512592
## Tiered Parking Fees Total
@@ -517,7 +597,8 @@ This policy states parking fees as such:
517597

518598
For example, if a vehicle is parked for 6.5 hours, it will be charged $10 on exit.
519599
File: [`tiered-parking-fees-total.json`](tiered-parking-fees-total.json)
520-
```
600+
601+
```json
521602
{
522603
"name": "Tiered Dwell Time Example",
523604
"description": "If parked for <1hr $2 upon exit, if parked for 1-2 hours $4 upon exit, if parked for longer than 2 hours $10 upon exit",
@@ -568,5 +649,5 @@ File: [`tiered-parking-fees-total.json`](tiered-parking-fees-total.json)
568649
]
569650
}
570651
```
571-
[Top](#table-of-contents)
572652

653+
[Top](#table-of-contents)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"name": "Tiered Dwell Time Example",
3+
"description": "First hour $2, second hour $4, every hour onwards $10",
4+
"policy_id": "2800cd0a-7827-4110-9713-b9e5bf29e9a1",
5+
"start_date": 1558389669540,
6+
"publish_date": 1558389669540,
7+
"end_date": null,
8+
"prev_policies": null,
9+
"provider_ids": [],
10+
"currency": "USD",
11+
"rules": [
12+
{
13+
"name": "0-1 Hour",
14+
"rule_id": "6b6fe61b-dbe5-4367-8e35-84fb14d23c54",
15+
"rule_type": "time",
16+
"rule_units": "hours",
17+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
18+
"statuses": { "available": [], "non_operational": [] },
19+
"vehicle_types": ["bicycle", "scooter"],
20+
"maximum": 1,
21+
"inclusive_maximum": false,
22+
"rate_applies_when": "in_bounds",
23+
"rate_amount": 200,
24+
"rate_recurrence": "each_time_unit"
25+
},
26+
{
27+
"name": "1-2 Hours",
28+
"rule_id": "edd6a195-bb30-4eb5-a2cc-44e5a18798a2",
29+
"rule_type": "time",
30+
"rule_units": "hours",
31+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
32+
"statuses": { "available": [], "non_operational": [] },
33+
"vehicle_types": ["bicycle", "scooter"],
34+
"minimum": 1,
35+
"maximum": 2,
36+
"inclusive_minimum": true,
37+
"inclusive_maximum": false,
38+
"rate_applies_when": "in_bounds",
39+
"rate_amount": 400,
40+
"rate_recurrence": "each_time_unit"
41+
},
42+
{
43+
"name": "> 2 hours",
44+
"rule_id": "9cd1768c-ab9e-484c-93f8-72a7078aa7b9",
45+
"rule_type": "time",
46+
"rule_units": "hours",
47+
"geographies": ["0c77c813-bece-4e8a-84fd-f99af777d198"],
48+
"statuses": { "available": [], "non_operational": [] },
49+
"vehicle_types": ["bicycle", "scooter"],
50+
"minimum": 2,
51+
"inclusive_minimum": true,
52+
"rate_applies_when": "in_bounds",
53+
"rate_amount": 1000,
54+
"rate_recurrence": "each_time_unit"
55+
}
56+
]
57+
}

policy/policy.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,26 @@
206206
"string",
207207
"null"
208208
],
209-
"description": "Specify when a rate is applied \u00e2\u20ac\u201c either once, or periodically according to a time unit specified using rule_units",
209+
"description": "Specify how a rate is applied \u00e2\u20ac\u201c either once, or periodically according to a time unit specified using rule_units",
210210
"enum": [
211-
"once",
211+
"once_on_match",
212+
"once_on_unmatch",
212213
"each_time_unit",
213214
"per_complete_time_unit"
214215
]
215216
},
217+
"rate_applies_when": {
218+
"$id": "#/definitions/rule/properties/rate_applies_when",
219+
"type": [
220+
"string",
221+
"null"
222+
],
223+
"description": "Specify when a rate is applicable to an event or count: when it's within rule bounds or when it is not",
224+
"enum": [
225+
"in_bounds",
226+
"out_of_bounds"
227+
]
228+
},
216229
"start_time": {
217230
"$id": "#/definitions/rule/properties/start_time",
218231
"$ref": "#/definitions/null_iso_time",

schema/templates/policy/policy.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,23 @@
189189
"rate_recurrence": {
190190
"$id": "#/definitions/rule/properties/rate_recurrence",
191191
"type": ["string", "null"],
192-
"description": "Specify when a rate is applied – either once, or periodically according to a time unit specified using rule_units",
192+
"description": "Specify how a rate is applied – either once, or periodically according to a time unit specified using rule_units",
193193
"enum": [
194-
"once",
194+
"once_on_match",
195+
"once_on_unmatch",
195196
"each_time_unit",
196197
"per_complete_time_unit"
197198
]
198199
},
200+
"rate_applies_when": {
201+
"$id": "#/definitions/rule/properties/rate_applies_when",
202+
"type": ["string", "null"],
203+
"description": "Specify when a rate is applicable to an event or count: when it's within rule bounds or when it is not",
204+
"enum": [
205+
"in_bounds",
206+
"out_of_bounds"
207+
]
208+
},
199209
"start_time": {
200210
"$id": "#/definitions/rule/properties/start_time",
201211
"$ref": "#/definitions/null_iso_time",

0 commit comments

Comments
 (0)