Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 0.22.0: Caching probabilities calculation across objects #79

Merged
merged 5 commits into from
Jul 2, 2020
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
4 changes: 3 additions & 1 deletion .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ clean: true
author: Samasaur
author_url: https://github.com/Samasaur1
module: DiceKit
module_version: 0.21.0
module_version: 0.22.0
# docset_icon:
github_url: https://github.com/Samasaur1/DiceKit
# github_file_prefix:
Expand All @@ -26,3 +26,5 @@ custom_categories:
children:
- Chances
- Chance
- Caching
- ENABLE_CACHING
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Upcoming]

## [0.22.0] — 2020-07-02
### Added
- More documentation on the `chances` property introduced in v0.21.0
- `Dice` caches the result of its computations for `probabilities` between objects (closes [#78](https://github.com/Samasaur1/DiceKit/issues/78)). See the issue (linked) or the pull request [here](https://github.com/Samasaur1/DiceKit/pull/79) for more information on caching.
- `Dice` now conforms to `Hashable` (adding for caching, but handy in general)

## [0.21.0] — 2020-07-01
### Added
- The internal `Chances` property formerly named `dict` (of type `[Roll: Chance]`) is now public and named `chances`.
Expand Down Expand Up @@ -241,6 +247,7 @@ Update .travis.yml in case https://swiftenv.fuller.li/install.sh is down/has no
- `Rollable`: a protocol for anything that is rollable

[Upcoming]: https://github.com/Samasaur1/DiceKit/compare/development
[0.22.0]: https://github.com/Samasaur1/DiceKit/compare/v0.21.0...v0.22.0
[0.21.0]: https://github.com/Samasaur1/DiceKit/compare/v0.20.2...v0.21.0
[0.20.2]: https://github.com/Samasaur1/DiceKit/compare/v0.20.1...v0.20.2
[0.20.1]: https://github.com/Samasaur1/DiceKit/compare/v0.20.0...v0.20.1
Expand Down
40 changes: 40 additions & 0 deletions Sources/DiceKit/Caching.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/// An object that caches the results of intensive computations.
///
/// In DiceKit, the only cached values are probability computations,
/// which can be very intensive.
///
/// The results of rolling are **NOT** cached.
///
/// **Implemented By**
/// * `Dice`
///
/// See `ENABLE_CACHING` for configuring caching of all `Caching` types.
///
/// - Since: 0.22.0
/// - Author: Samasaur
public protocol Caching {
/// Whether or not caching is enabled.
static var enableCaching: Bool { get set }
}

/// Whether or not DiceKit types should cache the results of probability computations across objects.
///
/// The results of rolling are **NOT** cached.
///
/// Every type that supports caching has its own `enableCaching` property.
/// Setting this property overwrites each type's configuration.
/// This property returns `true` when *every* supported type has caching enabled,
/// and `false` when *any* supported type has caching disabled.
///
/// **Types that currently support caching:**
/// * `Dice`
///
/// - Since: 0.22.0
public var ENABLE_CACHING: Bool {
get {
return Dice.enableCaching
}
set {
Dice.enableCaching = newValue
}
}
14 changes: 14 additions & 0 deletions Sources/DiceKit/Chances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ public struct Chances {
}
}
/// The rolls and the chances of them occurring.
///
/// This is the property one should use in order to iterate through the possibilities, like so:
///
/// ```
/// let chances: Chances = getChancesFromSomewhereElse()
/// let arr = chances.chances.sorted(by: { first, second in
/// first.key < second.key
/// })
/// for (roll, chance) in arr {
/// print("The chance of rolling a \(roll) is \(chance.n) out of \(chance.d)")
/// }
/// ```
///
/// - Since: 0.21.0
public private(set) var chances: [Roll: Chance]
/// The chance of the given roll occurring.
///
Expand Down
41 changes: 39 additions & 2 deletions Sources/DiceKit/Dice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// The properties of `Dice` objects are immutable; use the addition operators to combine them with other `Die` objects or modifiers. You can use compound assignment operators if you want, so long as you declare the `Dice` object as a `var` instead of a `let` constant.
///
/// - Author: Samasaur
public struct Dice {
public struct Dice: Caching {
/// The dice that make up this collection, along with how many times they appear.
///
/// This `[Die: Int]` dictionary stores the types of dice that appear, paired with the number of times they appear. For example:
Expand Down Expand Up @@ -266,9 +266,39 @@ public struct Dice {

/// The probabilities of all possible rolls.
///
/// Since 0.22.0, caches previous computations, even if they were on different objects.
/// See `enableCaching`, `ENABLE_CACHING` for caching configuration
///
/// - Since: 0.17.0
public var probabilities: Chances {
return __probabilities.value(input: self)
if let val = Dice.__cache?[self] {
return val
}
let val = __probabilities.value(input: self)
Dice.__cache?[self] = val
return val
}

fileprivate static var __cache: [Dice: Chances]? = [:]

/// Whether or not `Dice` should cache the results of probability computations across objects.
///
/// **Note:** The results of rolling are **NOT** cached.
///
/// Setting this value to `false` and then to `true` will clear the cache.
/// See `ENABLE_CACHING` for configuration of caching for all types at once.
///
/// - Since: 0.22.0
public static var enableCaching = true {
didSet {
if enableCaching == false {
__cache = nil
} else {
if __cache == nil {
__cache = [:]
}
}
}
}
}

Expand Down Expand Up @@ -421,6 +451,13 @@ extension Dice: Equatable {
}
}

extension Dice: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.dice)
hasher.combine(self.modifier)
}
}

extension Dice: Describable {
/// A description of this `Dice` object.
///
Expand Down
4 changes: 4 additions & 0 deletions Sources/DiceKit/Typealiases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ public typealias DKWeightedDie = WeightedDie
public typealias DKChance = Chance
/// See `Chances`.
public typealias DKChances = Chances
/// See `Caching`.
///
/// - Since: 0.22.0
public typealias DKCaching = Caching
5 changes: 5 additions & 0 deletions Tests/DiceKitTests/ChancesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@ final class ChancesTests: XCTestCase {

XCTAssertAllEqual(c, c2, c3)
}

func testSubscriptAndDictionaryProperty() {
let c = Chances(chances: [5: 0.234, 8: 0.432])
XCTAssertEqual(c.chances[5], c[of: 5])
}
}
1 change: 1 addition & 0 deletions Tests/DiceKitTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extension ChancesTests {
("testHashable", testHashable),
("testInitialization", testInitialization),
("testSubscript", testSubscript),
("testSubscriptAndDictionaryProperty", testSubscriptAndDictionaryProperty),
]
}

Expand Down
1 change: 0 additions & 1 deletion Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ var tests = [XCTestCaseEntry]()
tests += DiceKitTests.__allTests()

XCTMain(tests)