Skip to content

Commit

Permalink
Merge pull request #3 from twocentstudios/time-attack
Browse files Browse the repository at this point in the history
Add question/time limit quiz modes
  • Loading branch information
twocentstudios committed Nov 7, 2023
2 parents dd3e699 + 41ec9d2 commit abb5839
Show file tree
Hide file tree
Showing 14 changed files with 776 additions and 185 deletions.
89 changes: 89 additions & 0 deletions Dependencies/SessionSettings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import DependenciesAdditions
import Foundation

struct SessionSettingsClient {
var get: @Sendable () -> (SessionSettings)
var set: @Sendable (SessionSettings) throws -> Void
}

struct SessionSettings: Equatable, Codable {
enum QuizMode: Equatable, Identifiable, Codable, CaseIterable {
case infinite
case questionLimit
case timeLimit

var id: Self { self }
var title: String {
switch self {
case .infinite: "Infinite"
case .questionLimit: "Question Limit"
case .timeLimit: "Time Limit"
}
}
}
var quizMode: QuizMode
var questionLimit: Int
var timeLimit: Int // seconds

var showProgress: Bool
var showBiki: Bool
var showConfetti: Bool
var playHaptics: Bool
}

extension SessionSettings {
static let `default`: Self = .init(quizMode: .infinite, questionLimit: 10, timeLimit: 60, showProgress: true, showBiki: true, showConfetti: true, playHaptics: true)

static let questionLimitValues: [Int] = [5, 10, 20, 30, 50, 100]
static let timeLimitValues: [Int] = [30, 1 * 60, 3 * 60, 5 * 60, 10 * 60, 20 * 60]
}

extension SessionSettingsClient: DependencyKey {
static let settingsKey = "SessionSettingsClient.settings"
static var liveValue: Self {
@Dependency(\.userDefaults) var userDefaults
@Dependency(\.encode) var encode
@Dependency(\.decode) var decode
return .init(
get: {
let data = userDefaults.data(forKey: settingsKey)
let value: SessionSettings
if let data {
value = (try? decode(SessionSettings.self, from: data)) ?? SessionSettings.default
} else {
value = SessionSettings.default
}
return value
},
set: { newValue in
let data = try encode(newValue)
userDefaults.set(data, forKey: settingsKey)
}
)
}
}

extension SessionSettingsClient: TestDependencyKey {
static var previewValue: Self {
let storage = LockIsolated(SessionSettings.default)
return .init(
get: { storage.value },
set: { storage.setValue($0) }
)
}

static var testValue: Self {
let storage = LockIsolated(SessionSettings.default)
return .init(
get: { storage.value },
set: { storage.setValue($0) }
)
}
}

extension DependencyValues {
var sessionSettingsClient: SessionSettingsClient {
get { self[SessionSettingsClient.self] }
set { self[SessionSettingsClient.self] = newValue }
}
}
58 changes: 0 additions & 58 deletions Dependencies/TopicSettings.swift

This file was deleted.

12 changes: 12 additions & 0 deletions Utilities/Clamped.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// https://stackoverflow.com/a/40868784
extension Comparable {
func clamped(to limits: ClosedRange<Self>) -> Self {
min(max(self, limits.lowerBound), limits.upperBound)
}
}

extension BinaryFloatingPoint {
func clampedPercentage() -> Self {
clamped(to: 0.0 ... 1.0)
}
}
20 changes: 16 additions & 4 deletions count.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,16 @@
349A81732AF517AD00782538 /* ListeningQuizNavigationFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349A81722AF517AD00782538 /* ListeningQuizNavigationFeature.swift */; };
349D047A2A84EB3A008AFD0A /* SettingsFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349D04792A84EB3A008AFD0A /* SettingsFeature.swift */; };
349D047D2A88E569008AFD0A /* Topic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349D047C2A88E569008AFD0A /* Topic.swift */; };
349D04802A88F23F008AFD0A /* TopicSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349D047F2A88F23F008AFD0A /* TopicSettings.swift */; };
349D04802A88F23F008AFD0A /* SessionSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349D047F2A88F23F008AFD0A /* SessionSettings.swift */; };
34A9749A2A7AB0E600E6F672 /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = 34A974992A7AB0E600E6F672 /* ComposableArchitecture */; };
34AD2C9A2AF276DB00422C2B /* SessionSummaryFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34AD2C992AF276DB00422C2B /* SessionSummaryFeature.swift */; };
34BDC4952AA58A51001EF005 /* GetMoreVoicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BDC4942AA58A51001EF005 /* GetMoreVoicesView.swift */; };
34BDC4972AA5C2B6001EF005 /* Haptics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BDC4962AA5C2B6001EF005 /* Haptics.swift */; };
34E2E3EA2AA8C821002B511A /* TopicsFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E2E3E92AA8C821002B511A /* TopicsFeature.swift */; };
34E2E3EE2AA9C86A002B511A /* ConfettiSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 34E2E3ED2AA9C86A002B511A /* ConfettiSwiftUI */; };
34E53DC42AF793DC007E4BAE /* DeterminiteProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E53DC32AF793DC007E4BAE /* DeterminiteProgressView.swift */; };
34E53DC62AF7AD32007E4BAE /* Clamped.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E53DC52AF7AD32007E4BAE /* Clamped.swift */; };
34E53DC82AF7C2D8007E4BAE /* PreSettingsFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E53DC72AF7C2D8007E4BAE /* PreSettingsFeature.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -86,11 +89,14 @@
349A81722AF517AD00782538 /* ListeningQuizNavigationFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListeningQuizNavigationFeature.swift; sourceTree = "<group>"; };
349D04792A84EB3A008AFD0A /* SettingsFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFeature.swift; sourceTree = "<group>"; };
349D047C2A88E569008AFD0A /* Topic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Topic.swift; sourceTree = "<group>"; };
349D047F2A88F23F008AFD0A /* TopicSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopicSettings.swift; sourceTree = "<group>"; };
349D047F2A88F23F008AFD0A /* SessionSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionSettings.swift; sourceTree = "<group>"; };
34AD2C992AF276DB00422C2B /* SessionSummaryFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionSummaryFeature.swift; sourceTree = "<group>"; };
34BDC4942AA58A51001EF005 /* GetMoreVoicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetMoreVoicesView.swift; sourceTree = "<group>"; };
34BDC4962AA5C2B6001EF005 /* Haptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Haptics.swift; sourceTree = "<group>"; };
34E2E3E92AA8C821002B511A /* TopicsFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopicsFeature.swift; sourceTree = "<group>"; };
34E53DC32AF793DC007E4BAE /* DeterminiteProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeterminiteProgressView.swift; sourceTree = "<group>"; };
34E53DC52AF7AD32007E4BAE /* Clamped.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clamped.swift; sourceTree = "<group>"; };
34E53DC72AF7C2D8007E4BAE /* PreSettingsFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreSettingsFeature.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -176,7 +182,7 @@
children = (
340E70522A820E73004B124B /* SpeechSynthesis.swift */,
340E70572A83738F004B124B /* SpeechSynthesisSettings.swift */,
349D047F2A88F23F008AFD0A /* TopicSettings.swift */,
349D047F2A88F23F008AFD0A /* SessionSettings.swift */,
349D047C2A88E569008AFD0A /* Topic.swift */,
34BDC4962AA5C2B6001EF005 /* Haptics.swift */,
344242202ABDBDA8001E2FC8 /* AppIcon.swift */,
Expand All @@ -198,6 +204,7 @@
children = (
344242312AC41EAD001E2FC8 /* DataState.swift */,
344242362AC41F9C001E2FC8 /* EquatableError.swift */,
34E53DC52AF7AD32007E4BAE /* Clamped.swift */,
);
path = Utilities;
sourceTree = "<group>";
Expand All @@ -215,6 +222,7 @@
349D04792A84EB3A008AFD0A /* SettingsFeature.swift */,
34276FBE2AB34EB600647AE9 /* TextSpeechFeature.swift */,
34E2E3E92AA8C821002B511A /* TopicsFeature.swift */,
34E53DC72AF7C2D8007E4BAE /* PreSettingsFeature.swift */,
);
path = Feature;
sourceTree = "<group>";
Expand All @@ -225,6 +233,7 @@
348000E42A9CCD4700E7CCEE /* CountBikiView.swift */,
34BDC4942AA58A51001EF005 /* GetMoreVoicesView.swift */,
349802212A7BDDF200E352F5 /* IndeterminiteProgressView.swift */,
34E53DC32AF793DC007E4BAE /* DeterminiteProgressView.swift */,
340B48D02AE8ACDD0046B31C /* StrokeFillShape.swift */,
);
path = View;
Expand Down Expand Up @@ -349,6 +358,7 @@
files = (
340B48D12AE8ACDD0046B31C /* StrokeFillShape.swift in Sources */,
34AD2C9A2AF276DB00422C2B /* SessionSummaryFeature.swift in Sources */,
34E53DC62AF7AD32007E4BAE /* Clamped.swift in Sources */,
344242252ABDDEA7001E2FC8 /* TranslyvaniaTierFeature.swift in Sources */,
34E2E3EA2AA8C821002B511A /* TopicsFeature.swift in Sources */,
3478331F2AA7343A005160DC /* PlanningTopicsFeature.swift in Sources */,
Expand All @@ -357,21 +367,23 @@
340E70582A83738F004B124B /* SpeechSynthesisSettings.swift in Sources */,
344242272ABEBD6F001E2FC8 /* TierProducts.swift in Sources */,
34BDC4972AA5C2B6001EF005 /* Haptics.swift in Sources */,
349D04802A88F23F008AFD0A /* TopicSettings.swift in Sources */,
349D04802A88F23F008AFD0A /* SessionSettings.swift in Sources */,
34BDC4952AA58A51001EF005 /* GetMoreVoicesView.swift in Sources */,
3442422E2AC1D11A001E2FC8 /* TierPurchaseHistory.swift in Sources */,
349802222A7BDDF200E352F5 /* IndeterminiteProgressView.swift in Sources */,
344242342AC41EAD001E2FC8 /* DataState.swift in Sources */,
348000E52A9CCD4700E7CCEE /* CountBikiView.swift in Sources */,
34276FBF2AB34EB600647AE9 /* TextSpeechFeature.swift in Sources */,
349D047A2A84EB3A008AFD0A /* SettingsFeature.swift in Sources */,
34E53DC42AF793DC007E4BAE /* DeterminiteProgressView.swift in Sources */,
340E70532A820E73004B124B /* SpeechSynthesis.swift in Sources */,
340A51CD2A78EC78007DCA0C /* App.swift in Sources */,
344242232ABDD814001E2FC8 /* AppIconFeature.swift in Sources */,
344242372AC41F9C001E2FC8 /* EquatableError.swift in Sources */,
349A81732AF517AD00782538 /* ListeningQuizNavigationFeature.swift in Sources */,
34276FC42AB5899C00647AE9 /* AboutFeature.swift in Sources */,
349D047D2A88E569008AFD0A /* Topic.swift in Sources */,
34E53DC82AF7C2D8007E4BAE /* PreSettingsFeature.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,37 +48,37 @@
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "937e904258d22af6e447a0b72c0bc67583ef64a2",
"version" : "1.0.4"
"revision" : "a902f1823a7ff3c9ab2fba0f992396b948eda307",
"version" : "1.0.5"
}
},
{
"identity" : "swift-composable-architecture",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-composable-architecture.git",
"state" : {
"revision" : "195284b94b799b326729640453f547f08892293a",
"version" : "1.0.0"
"revision" : "9b0f600253f467f61cbd53f60ccc243cc4ff27cd",
"version" : "1.3.0"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "ea631ce892687f5432a833312292b80db238186a",
"version" : "1.0.0"
"revision" : "6155400cb15b0d99b2c257d57603d61d03a817a8",
"version" : "1.0.1"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "edd66cace818e1b1c6f1b3349bb1d8e00d6f8b01",
"version" : "1.0.0"
"revision" : "65fc9e2b62727cacfab9fc60d580c284a4b9308c",
"version" : "1.1.1"
}
},
{
Expand Down Expand Up @@ -113,17 +113,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swiftui-navigation",
"state" : {
"revision" : "f5bcdac5b6bb3f826916b14705f37a3937c2fd34",
"version" : "1.0.0"
"revision" : "74adfb8e48724c50d0ac148c658ae5fa7dfd6b6d",
"version" : "1.0.3"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "302891700c7fa3b92ebde9fe7b42933f8349f3c7",
"version" : "1.0.0"
"revision" : "23cbf2294e350076ea4dbd7d5d047c1e76b03631",
"version" : "1.0.2"
}
}
],
Expand Down
2 changes: 1 addition & 1 deletion count/Feature/AboutFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import StoreKit
import SwiftUI

struct AboutFeature: Reducer {
struct State: Equatable {
struct State: Equatable, Sendable {
var appIcon: AppIconFeature.State
var transylvaniaTier: TransylvaniaTierFeature.State

Expand Down

0 comments on commit abb5839

Please sign in to comment.