From cee4f24e93fc417ea6c983f65a8ce3917034c51e Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Sat, 13 Feb 2021 20:32:58 -0800 Subject: [PATCH] Started adding skills. --- iOS/MonsterCards.xcodeproj/project.pbxproj | 40 +++++++-- .../Models/Enums/AbilityScore.swift | 53 ++++++++++++ .../Models/{ => Enums}/AdvantageType.swift | 0 .../Models/{ => Enums}/ProficiencyType.swift | 0 .../Models/Monster+CoreDataClass.swift | 32 ++++++++ .../Models/MonsterViewModel.swift | 8 ++ .../Models/Skill+CoreDataClass.swift | 63 +++++++++++++++ iOS/MonsterCards/Models/SkillViewModel.swift | 38 +++++++++ .../MonsterCards.xcdatamodel/contents | 10 ++- iOS/MonsterCards/Views/EditMonster.swift | 81 ++++++++++++++++++- 10 files changed, 315 insertions(+), 10 deletions(-) create mode 100644 iOS/MonsterCards/Models/Enums/AbilityScore.swift rename iOS/MonsterCards/Models/{ => Enums}/AdvantageType.swift (100%) rename iOS/MonsterCards/Models/{ => Enums}/ProficiencyType.swift (100%) create mode 100644 iOS/MonsterCards/Models/MonsterViewModel.swift create mode 100644 iOS/MonsterCards/Models/Skill+CoreDataClass.swift create mode 100644 iOS/MonsterCards/Models/SkillViewModel.swift diff --git a/iOS/MonsterCards.xcodeproj/project.pbxproj b/iOS/MonsterCards.xcodeproj/project.pbxproj index cb18033..7627cd3 100644 --- a/iOS/MonsterCards.xcodeproj/project.pbxproj +++ b/iOS/MonsterCards.xcodeproj/project.pbxproj @@ -7,8 +7,12 @@ objects = { /* Begin PBXBuildFile section */ - E210B83025B426570083EAC5 /* ProficiencyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E210B82F25B426570083EAC5 /* ProficiencyType.swift */; }; - E210B83525B428A30083EAC5 /* AdvantageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E210B83425B428A30083EAC5 /* AdvantageType.swift */; }; + E20209D325D8DD9600EFE733 /* Skill+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209D225D8DD9600EFE733 /* Skill+CoreDataClass.swift */; }; + E20209E825D8DEC100EFE733 /* AbilityScore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209E725D8DEC100EFE733 /* AbilityScore.swift */; }; + E20209F425D8E04300EFE733 /* ProficiencyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209F225D8E04300EFE733 /* ProficiencyType.swift */; }; + E20209F525D8E04300EFE733 /* AdvantageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209F325D8E04300EFE733 /* AdvantageType.swift */; }; + E20209FB25D8E19100EFE733 /* SkillViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209F925D8E19100EFE733 /* SkillViewModel.swift */; }; + E20209FC25D8E19100EFE733 /* MonsterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20209FA25D8E19100EFE733 /* MonsterViewModel.swift */; }; E210B83A25B42D980083EAC5 /* MCProficiencyPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = E210B83925B42D980083EAC5 /* MCProficiencyPicker.swift */; }; E210B83F25B42DAB0083EAC5 /* MCAdvantagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = E210B83E25B42DAB0083EAC5 /* MCAdvantagePicker.swift */; }; E2182E6425B22F8A00DFAEF8 /* Monster+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2182E6225B22F8A00DFAEF8 /* Monster+CoreDataClass.swift */; }; @@ -51,8 +55,12 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - E210B82F25B426570083EAC5 /* ProficiencyType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProficiencyType.swift; sourceTree = ""; }; - E210B83425B428A30083EAC5 /* AdvantageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantageType.swift; sourceTree = ""; }; + E20209D225D8DD9600EFE733 /* Skill+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Skill+CoreDataClass.swift"; sourceTree = ""; }; + E20209E725D8DEC100EFE733 /* AbilityScore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbilityScore.swift; sourceTree = ""; }; + E20209F225D8E04300EFE733 /* ProficiencyType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProficiencyType.swift; sourceTree = ""; }; + E20209F325D8E04300EFE733 /* AdvantageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvantageType.swift; sourceTree = ""; }; + E20209F925D8E19100EFE733 /* SkillViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SkillViewModel.swift; sourceTree = ""; }; + E20209FA25D8E19100EFE733 /* MonsterViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MonsterViewModel.swift; sourceTree = ""; }; E210B83925B42D980083EAC5 /* MCProficiencyPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCProficiencyPicker.swift; sourceTree = ""; }; E210B83E25B42DAB0083EAC5 /* MCAdvantagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCAdvantagePicker.swift; sourceTree = ""; }; E2182E6225B22F8A00DFAEF8 /* Monster+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Monster+CoreDataClass.swift"; sourceTree = ""; }; @@ -108,6 +116,16 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + E20209E625D8DEB600EFE733 /* Enums */ = { + isa = PBXGroup; + children = ( + E20209F325D8E04300EFE733 /* AdvantageType.swift */, + E20209F225D8E04300EFE733 /* ProficiencyType.swift */, + E20209E725D8DEC100EFE733 /* AbilityScore.swift */, + ); + path = Enums; + sourceTree = ""; + }; E2570FAC25B1AC520055B23B = { isa = PBXGroup; children = ( @@ -193,9 +211,11 @@ E257101225B1B2790055B23B /* Models */ = { isa = PBXGroup; children = ( + E20209FA25D8E19100EFE733 /* MonsterViewModel.swift */, + E20209F925D8E19100EFE733 /* SkillViewModel.swift */, + E20209E625D8DEB600EFE733 /* Enums */, E2182E6225B22F8A00DFAEF8 /* Monster+CoreDataClass.swift */, - E210B82F25B426570083EAC5 /* ProficiencyType.swift */, - E210B83425B428A30083EAC5 /* AdvantageType.swift */, + E20209D225D8DD9600EFE733 /* Skill+CoreDataClass.swift */, ); path = Models; sourceTree = ""; @@ -337,6 +357,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E20209FB25D8E19100EFE733 /* SkillViewModel.swift in Sources */, E2570FC225B1AC550055B23B /* Persistence.swift in Sources */, E2570FBB25B1AC520055B23B /* ContentView.swift in Sources */, E2570FC525B1AC550055B23B /* MonsterCards.xcdatamodeld in Sources */, @@ -348,13 +369,16 @@ E2B5285925B3028700AAA69E /* EditMonster.swift in Sources */, E2570FF525B1ADEB0055B23B /* Dashboard.swift in Sources */, E257100425B1AF4A0055B23B /* SearchBar.swift in Sources */, + E20209F525D8E04300EFE733 /* AdvantageType.swift in Sources */, + E20209FC25D8E19100EFE733 /* MonsterViewModel.swift in Sources */, E2570FFF25B1AE180055B23B /* Library.swift in Sources */, E2BD703125B3BBB90058ED69 /* MCStepperField.swift in Sources */, - E210B83525B428A30083EAC5 /* AdvantageType.swift in Sources */, + E20209F425D8E04300EFE733 /* ProficiencyType.swift in Sources */, E2570FFA25B1AE020055B23B /* Collections.swift in Sources */, E2570FB925B1AC520055B23B /* MonsterCardsApp.swift in Sources */, - E210B83025B426570083EAC5 /* ProficiencyType.swift in Sources */, + E20209D325D8DD9600EFE733 /* Skill+CoreDataClass.swift in Sources */, E2BD702C25B3A8D70058ED69 /* MCTextField.swift in Sources */, + E20209E825D8DEC100EFE733 /* AbilityScore.swift in Sources */, E210B83F25B42DAB0083EAC5 /* MCAdvantagePicker.swift in Sources */, E26CDA2B25CFB38E00E3F50D /* MCArmorTypePicker.swift in Sources */, ); diff --git a/iOS/MonsterCards/Models/Enums/AbilityScore.swift b/iOS/MonsterCards/Models/Enums/AbilityScore.swift new file mode 100644 index 0000000..0789b60 --- /dev/null +++ b/iOS/MonsterCards/Models/Enums/AbilityScore.swift @@ -0,0 +1,53 @@ +// +// AbilityScore.swift +// MonsterCards +// +// Created by Tom Hicks on 1/18/21. +// + +import Foundation + +enum AbilityScore: String, CaseIterable, Identifiable { + case strength = "strength" + case dexterity = "dexterity" + case constitution = "constitution" + case intelligence = "intelligence" + case wisdom = "wisdom" + case charisma = "charisma" + + var id: AbilityScore { self } + + var displayName: String { + switch self { + case .strength: + return "Strength" + case .dexterity: + return "Dexterity" + case .constitution: + return "Constitution" + case .intelligence: + return "Intelligence" + case .wisdom: + return "Wisdom" + case .charisma: + return "Charisma" + } + } + + var shortDisplayName: String { + switch self { + case .strength: + return "STR" + case .dexterity: + return "DEX" + case .constitution: + return "CON" + case .intelligence: + return "INT" + case .wisdom: + return "WIS" + case .charisma: + return "CHA" + } + } +} diff --git a/iOS/MonsterCards/Models/AdvantageType.swift b/iOS/MonsterCards/Models/Enums/AdvantageType.swift similarity index 100% rename from iOS/MonsterCards/Models/AdvantageType.swift rename to iOS/MonsterCards/Models/Enums/AdvantageType.swift diff --git a/iOS/MonsterCards/Models/ProficiencyType.swift b/iOS/MonsterCards/Models/Enums/ProficiencyType.swift similarity index 100% rename from iOS/MonsterCards/Models/ProficiencyType.swift rename to iOS/MonsterCards/Models/Enums/ProficiencyType.swift diff --git a/iOS/MonsterCards/Models/Monster+CoreDataClass.swift b/iOS/MonsterCards/Models/Monster+CoreDataClass.swift index f7a9233..16fe272 100644 --- a/iOS/MonsterCards/Models/Monster+CoreDataClass.swift +++ b/iOS/MonsterCards/Models/Monster+CoreDataClass.swift @@ -137,6 +137,23 @@ public class Monster: NSManagedObject { return Int(floor(Double((score - 10)) / 2.0)) } + func abilityModifierForAbilityScore(_ abilityScore: AbilityScore) -> Int { + switch abilityScore { + case .strength: + return strengthModifier; + case .dexterity: + return dexterityModifier + case .constitution: + return constitutionModifier + case .intelligence: + return intelligenceModifier + case .wisdom: + return wisdomModifier + case .charisma: + return charismaModifier + } + } + var strengthModifier: Int { get { return Monster.abilityModifierForScore(Int(strengthScore)) @@ -587,6 +604,21 @@ public class Monster: NSManagedObject { } } + // MARK: Skills + + var skillsDescription: String { + get { + return "" + } + } + + var skillsArray: [Skill] { + let set = skills as? Set ?? [] + return set.sorted { + $0.wrappedName < $1.wrappedName + } + } + // MARK: End } diff --git a/iOS/MonsterCards/Models/MonsterViewModel.swift b/iOS/MonsterCards/Models/MonsterViewModel.swift new file mode 100644 index 0000000..b7729d5 --- /dev/null +++ b/iOS/MonsterCards/Models/MonsterViewModel.swift @@ -0,0 +1,8 @@ +// +// MonsterViewModel.swift +// MonsterCards +// +// Created by Tom Hicks on 1/18/21. +// + +import Foundation diff --git a/iOS/MonsterCards/Models/Skill+CoreDataClass.swift b/iOS/MonsterCards/Models/Skill+CoreDataClass.swift new file mode 100644 index 0000000..b1dd446 --- /dev/null +++ b/iOS/MonsterCards/Models/Skill+CoreDataClass.swift @@ -0,0 +1,63 @@ +// +// Skill+CoreDataClass.swift +// MonsterCards +// +// Created by Tom Hicks on 1/18/21. +// +// + +import Foundation +import CoreData + +@objc(Skill) +public class Skill: NSManagedObject { + + var wrappedName: String { + get { + return name ?? "" + } + set { + name = newValue + } + } + + + var wrappedProficiency: ProficiencyType { + get { + return ProficiencyType.init(rawValue: proficiency ?? "") ?? .none + } + set { + proficiency = newValue.rawValue + } + } + + var wrappedAbilityScore: AbilityScore { + get { + return AbilityScore.init(rawValue: abilityScoreName ?? "") ?? .strength + } + set { + abilityScoreName = newValue.rawValue + } + } + + var modifier: Int64 { + get { + let proficiencyBonus = Double(monster?.proficiencyBonus ?? 0) + let abilityScoreModifier = Double(monster?.abilityModifierForAbilityScore(wrappedAbilityScore) ?? 0) + switch wrappedProficiency { + case .none: + return Int64(abilityScoreModifier) + case .proficient: + return Int64(abilityScoreModifier + proficiencyBonus) + case .expertise: + return Int64(abilityScoreModifier + 2 * proficiencyBonus) + } + } + } + + var skillDescription: String { + get { + return String(format: "%@ %+d%@", name ?? "", modifier) + } + } +} diff --git a/iOS/MonsterCards/Models/SkillViewModel.swift b/iOS/MonsterCards/Models/SkillViewModel.swift new file mode 100644 index 0000000..4cae7bd --- /dev/null +++ b/iOS/MonsterCards/Models/SkillViewModel.swift @@ -0,0 +1,38 @@ +// +// SkillViewModel.swift +// MonsterCards +// +// Created by Tom Hicks on 1/18/21. +// + +import Foundation + +class SkillViewModel: ObservableObject { + + init(_ rawSkill: Skill?) { + if (rawSkill != nil) { + self.rawSkill = rawSkill + _name = rawSkill!.name ?? "" + } else { + _name = "" + } + } + + var rawSkill: Skill? + + private var _name: String = "" + var name: String { + get { + return _name + } + set { + if (newValue != _name) { + _name = newValue + // Notify changed name + } + if (rawSkill != nil) { + rawSkill!.name = newValue + } + } + } +} diff --git a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents index 95eeb7c..4a9c924 100644 --- a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents +++ b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents @@ -49,8 +49,16 @@ + + + + + + + - + + \ No newline at end of file diff --git a/iOS/MonsterCards/Views/EditMonster.swift b/iOS/MonsterCards/Views/EditMonster.swift index ac5a63a..f832412 100644 --- a/iOS/MonsterCards/Views/EditMonster.swift +++ b/iOS/MonsterCards/Views/EditMonster.swift @@ -54,7 +54,8 @@ struct EditMonster: View { @State private var monsterWisdomSavingThrowAdvantage: AdvantageType = .none @State private var monsterCharismaSavingThrowProficiency: ProficiencyType = .none @State private var monsterCharismaSavingThrowAdvantage: AdvantageType = .none - + @State private var monsterSkills: [Skill] = [] + var body: some View { List { @@ -258,6 +259,50 @@ struct EditMonster: View { } } .textCase(nil) + Section(header: HStack { + Text("Skills") + Spacer() + Button(action: addSkill) { + Image(systemName:"plus") + } + }) { + VStack { +// ForEach((1...10).reversed(), id: \.self) { +// Text("\($0)…") +// } +// List(monster.skillsArray) {_ in +// Text ("Name") +// } + ForEach(monsterSkills, id: \.self) { skill in + VStack { + Text("---") + Text(skill.wrappedName) + Text(skill.wrappedProficiency.displayName) + Text(skill.wrappedAbilityScore.displayName) + } + } + } + } + .textCase(nil) + +// Section(header: HStack { +// Text("Skills") +// Spacer() +// Button(action: addSkill) { +// Image(systemName:"plus") +// } +// }) { +// VStack { +//// let skills2: [Skill] = monster.skills?.allObjects) +// ForEach(monster.allSkills)) { skill in +// Text("A SKill") +// } +// } +//// ForEach(arrayLiteral: Array(monster.skills)) { skill in +//// Text("A Skill") +//// } +// } +// .textCase(nil) } .onAppear(perform: copyMonsterToLocal) .toolbar(content: { @@ -273,6 +318,29 @@ struct EditMonster: View { .navigationBarBackButtonHidden(true) } + private func addSkill() { + print("Add Skill pressed") + + let newSkill = Skill.init(context: viewContext) + newSkill.name = "Acrobatics" + newSkill.wrappedAbilityScore = .dexterity + newSkill.wrappedProficiency = .proficient + monster.addToSkills(newSkill); +// newSkill.monster = monster +// monster.addSkill(newSkill) +// (monster.skills as! NSMutableSet).add(newSkill) +// var s1: NSMutableSet = ["A", "S", "D", "F"] +// var s2: Set = ["A", "S", "D", "F"] +// s1.add +// + do { + try viewContext.save() + monsterSkills = monster.skillsArray + } catch { + print("error") + } + } + private func dismissView() { self.presentationMode.wrappedValue.dismiss() } @@ -376,6 +444,17 @@ struct EditMonster: View { monster.wisdomSavingThrowAdvantageEnum = monsterWisdomSavingThrowAdvantage monster.charismaSavingThrowProficiencyEnum = monsterCharismaSavingThrowProficiency monster.charismaSavingThrowAdvantageEnum = monsterCharismaSavingThrowAdvantage + monster.skills?.forEach { s in + let skill = s as! Skill + if (!monsterSkills.contains(skill)) { + monster.removeFromSkills(skill) + } + } + monster.skillsArray.forEach { skill in + if (!(monster.skills?.contains(skill) ?? false)) { + monster.addToSkills(skill) + } + } } }