diff --git a/ProjectClock/AddAlarmViewController.swift b/ProjectClock/AddAlarmViewController.swift
index 44c06ee..22e2017 100644
--- a/ProjectClock/AddAlarmViewController.swift
+++ b/ProjectClock/AddAlarmViewController.swift
@@ -9,6 +9,74 @@ import UIKit
class AddAlarmViewController: UIViewController
{
+<<<<<<< Updated upstream
+=======
+ // Editing variables
+ var alarmCell: AlarmTableCell? = nil
+ var editMode: Bool { alarmCell != nil }
+ var originalTime: String = ""
+
+ override func viewDidLoad()
+ {
+ // End edit on return
+ alarmNameTextField.delegate = self
+
+ // Load alarm to edit if in edit mode
+ if let alarmCell = alarmCell
+ {
+ // Toggle editing mode
+ viewTitle.text = "Edit Alarm"
+
+ // Convert string to Date
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateFormat = "h:mma"
+ let date = dateFormatter.date(from: "\(alarmCell.time.text!)\(alarmCell.ampm.text!)")
+
+ // Set all the original values to be edited
+ timePicker.date = date!
+ originalTime = String(dateFormatter.string(from: date!).dropLast(2))
+
+ // Toggle proper repeats
+ if let repeats = alarmCell.repeatText.text {
+ if repeats == "Repeats: Weekdays" {
+ repeatWeekdaysSwitch.isOn = true
+ repeatWeekendsSwitch.isOn = false
+ } else if repeats == "Repeats: Weekends" {
+ repeatWeekendsSwitch.isOn = true
+ repeatWeekdaysSwitch.isOn = false
+ } else if repeats == "Repeats: Daily" {
+ repeatWeekdaysSwitch.isOn = true
+ repeatWeekendsSwitch.isOn = true
+ } else {
+ repeatWeekendsSwitch.isOn = false
+ repeatWeekdaysSwitch.isOn = false
+ }
+ }
+
+ alarmNameTextField.text = String(alarmCell.descriptionText.text!.dropFirst(2))
+ updateETA()
+
+ // Sets the WVM
+ if let wvm = alarmCell.wvmText.text {
+ for index in 0...wvms.count-1 {
+ if wvm == wvms[index].name {
+ wvmPicker.selectRow(index, inComponent: 0, animated: true)
+ }
+ }
+ }
+
+ //Sets alarm tone
+ if let toneName = alarmCell.toneLabel.text {
+ for index in 0...ringtones.count-1 {
+ if toneName == ringtones[index].name {
+ ringtonePicker.selectRow(index, inComponent: 0, animated: true)
+ }
+ }
+ }
+ }
+ }
+
+>>>>>>> Stashed changes
// UI: Make scroll view scrollable
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var scrollViewInner: UIView!
@@ -24,7 +92,32 @@ class AddAlarmViewController: UIViewController
override func viewDidLoad()
{
+<<<<<<< Updated upstream
super.viewDidLoad()
+=======
+ let (h, m, _) = timePicker.date.getHMS()
+
+ // Create the alarm
+ let alarm = Alarm(hour: h, minute: m,
+ text: alarmNameTextField.text ?? "Alarm",
+ wakeMethod: wvms[wvmPicker.selectedRow(inComponent: 0)],
+ lastActivate: Date(), alarmTone: ringtones[ringtonePicker.selectedRow(inComponent: 0)].tone, toneName: ringtones[ringtonePicker.selectedRow(inComponent: 0)].name)
+
+ // Set alarm.repeats to correspond with what the user selects
+ (0...6).forEach { alarm.repeats[$0] = false }
+ if repeatWeekdaysSwitch.isOn { (1...5).forEach { alarm.repeats[$0] = true } }
+ if repeatWeekendsSwitch.isOn { [0, 6].forEach { alarm.repeats[$0] = true } }
+
+ return alarm
+ }
+
+ /**
+ Dynamically the ETA label for the alarm
+ */
+ func updateETA() {
+ let timeTill = createAlarm().nextActivate!.timeIntervalSince(Date()).str()
+ timeTillAlarmLabel.text = "Going off in \(timeTill)"
+>>>>>>> Stashed changes
}
}
diff --git a/ProjectClock/AlarmViewController.swift b/ProjectClock/AlarmViewController.swift
index 17b0dfd..b27ddbe 100644
--- a/ProjectClock/AlarmViewController.swift
+++ b/ProjectClock/AlarmViewController.swift
@@ -60,10 +60,72 @@ class AlarmTableCell: UITableViewCell
@IBOutlet weak var enable: UISwitch!
@IBOutlet weak var repeatText: UILabel!
@IBOutlet weak var goingOffText: UILabel!
+<<<<<<< Updated upstream
+=======
+ @IBOutlet weak var wvmText: UILabel!
+ @IBOutlet weak var toneLabel: UILabel!
+
+>>>>>>> Stashed changes
/// Update information on the cell to information in the alarm object
func setData(_ alarm: Alarm)
{
descriptionText.text = "- " + alarm.text
+<<<<<<< Updated upstream
+=======
+ enable.isOn = alarm.enabled
+ wvmText.text = alarm.wakeMethod.name
+ toneLabel.text = alarm.toneName
+
+ // Display Hour, Minute, and AM or PM
+ ampm.text = alarm.hour < 12 || alarm.hour == 24 ? "AM" : "PM"
+ var hour = alarm.hour <= 12 ? alarm.hour : alarm.hour - 12
+ hour = alarm.hour == 0 ? 12 : hour
+ time.text = String(format: "%i:%02i", hour, alarm.minute)
+
+ // displays the specific days alarm is activated
+ let daysDict = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]
+ var daysActive : [String] = []
+ if alarm.oneTime {repeatText.text = "One-time Alarm"}
+ else {
+ for (index, element) in alarm.repeats.enumerated() {
+ if element {
+ daysActive.append(daysDict[index])
+ }
+ }
+ if daysDict == daysActive {
+ repeatText.text = "Repeats: Daily"
+ } else if daysActive == ["Sun", "Sat"] {
+ repeatText.text = "Repeats: Weekends"
+ } else if daysActive == ["Mon", "Tues", "Wed", "Thurs", "Fri"] {
+ repeatText.text = "Repeats: Weekdays"
+ } else {
+ repeatText.text = daysActive.joined(separator: ", ")
+ }
+ }
+
+ updateActivationTime()
+ }
+
+ func updateActivationTime()
+ {
+ // Show next activation date
+ if alarm.enabled, let n = alarm.nextActivate {
+ goingOffText.text = "(Going off in \(n.timeIntervalSince(Date()).str()))"
+ }
+ else {
+ goingOffText.text = ""
+ }
+ }
+
+ /**
+ Called when the user switches the switch
+ */
+ @IBAction func switchChange(_ sender: Any)
+ {
+ Alarms.fromLocal().apply {
+ $0.list.first { $0.hour == self.alarm.hour && $0.minute == self.alarm.minute }?.enabled = enable.isOn
+ }.localSave()
+>>>>>>> Stashed changes
}
}
diff --git a/ProjectClock/Base.lproj/Main.storyboard b/ProjectClock/Base.lproj/Main.storyboard
index c30afe5..88ed345 100644
--- a/ProjectClock/Base.lproj/Main.storyboard
+++ b/ProjectClock/Base.lproj/Main.storyboard
@@ -67,10 +67,20 @@
+<<<<<<< Updated upstream
+=======
+
+>>>>>>> Stashed changes
@@ -94,6 +104,12 @@
+<<<<<<< Updated upstream
+=======
+
+
+
+>>>>>>> Stashed changes
@@ -583,6 +599,572 @@
+<<<<<<< Updated upstream
+=======
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+>>>>>>> Stashed changes
diff --git a/ProjectClock/Models.swift b/ProjectClock/Models.swift
index cdce614..78a39ec 100644
--- a/ProjectClock/Models.swift
+++ b/ProjectClock/Models.swift
@@ -11,6 +11,171 @@ struct User: Decodable
{
var id: Int
var name: String
+<<<<<<< Updated upstream
var email: String
var pass: String
+=======
+ var members: String
+ // And a hidden field: admin pin
+
+ var membersList: [String] { members.csv }
+
+ /// Save family to local storage
+ func localSave()
+ {
+ localStorage.setValue(JSON.stringify(self)!, forKey: "family")
+ }
+
+ /// Read family object from local storage
+ static func fromLocal() -> Family?
+ {
+ guard let f = localStorage.string(forKey: "family") else { return nil }
+ return JSON.parse(Family.self, f)
+ }
+}
+
+struct WVM: Codable
+{
+ let name: String
+ let desc: String
+}
+
+
+let wvms = [
+ WVM(name: "Shake", desc: "Shake your phone... aggresively!"),
+ WVM(name: "Math 1", desc: "Easy math expression"),
+ WVM(name: "Math 2", desc: "Medium math expression"),
+ WVM(name: "Math 3", desc: "Hard math expression"),
+ WVM(name: "Factor", desc: "Factor a binomial"),
+ WVM(name: "RPS", desc: "Win a game of rock paper scissors"),
+ //WVM(name: "Smash", desc: "It'll never turn off"),
+ //WVM(name: "Walk", desc: "Walk a few steps"),
+ //WVM(name: "Jump", desc: "Make a few jumps")
+]
+
+
+struct Tone: Codable{
+
+ let name: String
+ let tone: SystemSoundID
+
+}
+
+let ringtones = [
+ Tone(name: "News Flash", tone: SystemSoundID(1028)),
+ Tone(name: "Sherwood Forest", tone: SystemSoundID(1030)),
+ Tone(name: "Ladder", tone: SystemSoundID(1326)),
+ Tone(name: "Minuet", tone: SystemSoundID(1327)),
+ Tone(name: "Tock", tone: SystemSoundID(1306)),
+ Tone(name: "Bloom", tone: SystemSoundID(1321)),
+ Tone(name: "Calypso", tone: SystemSoundID(1322)),
+ Tone(name: "Train", tone: SystemSoundID(1323)),
+ Tone(name: "Fanfare", tone: SystemSoundID(1325))
+]
+
+class Alarm: Codable, Equatable
+{
+ static func == (lhs: Alarm, rhs: Alarm) -> Bool {
+ return lhs.hour == rhs.hour && lhs.minute == rhs.minute && lhs.text == rhs.text &&
+ lhs.alarmTone == rhs.alarmTone && lhs.repeats == rhs.repeats
+ }
+
+ var enabled: Bool
+ var hour: Int // Hour (24)
+ var minute: Int
+ var text: String
+ var wakeMethod: WVM
+ var alarmTone: SystemSoundID
+ var notificationID: String
+ var toneName: String
+
+ /// What days does it repeat (Sun, Mon, Tue, Wed, Thu, Fri, Sat)
+ var repeats: [Bool]
+
+ /// When is the last time that the alarm went off
+ var lastActivate: Date
+
+ /// Constructor
+ init(enabled: Bool = true,
+ hour: Int, minute: Int, text: String, wakeMethod: WVM,
+ repeats: [Bool] = [false, true, true, true, true, true, false],
+ lastActivate: Date = Date(),
+ alarmTone: SystemSoundID = ringtones[0].tone,
+ toneName: String = ""
+
+ )
+ {
+ self.enabled = enabled
+ self.hour = hour
+ self.minute = minute
+ self.text = text
+ self.wakeMethod = wakeMethod
+ self.repeats = repeats
+ self.lastActivate = lastActivate
+ self.alarmTone = alarmTone
+ self.notificationID = "notification.id.\(Int.random(in: 1...Int.max))"
+ self.toneName = toneName
+ }
+
+ /// Does it automatically disable after activating once
+ var oneTime: Bool { repeats.allSatisfy { !$0 } }
+
+ /// Get time in h:mm format
+ var timeText: String { String(format: "%i:%02i", hour, minute) }
+
+ /// When should the alarm activate next since lastActivate?
+ var nextActivate: Date?
+ {
+ let (y, m, d) = lastActivate.getYMD()
+ let (nh, nm, _) = lastActivate.getHMS()
+
+ // Create activation date
+ var date = Date.create(y, m, d, hour, minute)
+
+ // If it will activate tomorrow
+ if nh > hour || (nh == hour && nm >= minute) { date = date.added(.day, 1) }
+
+ // If it's one-time, don't have to check for repeating date
+ if oneTime { return date }
+
+ // Make sure it's repeating
+ guard (repeats.contains { $0 }) else { return nil }
+
+ // If the day is not one of the "repeat" days, keep adding 1 until it is
+ while !repeats[date.get(.weekday) - 1] { date = date.added(.day, 1) }
+
+ return date
+ }
+}
+
+class Alarms: Codable
+{
+ var list: [Alarm] = []
+
+ /// Save alarms to local storage
+ func localSave()
+ {
+ list.sort { ($0.hour * 60 + $0.minute) < ($1.hour * 60 + $1.minute) }
+ localStorage.setValue(JSON.stringify(list)!, forKey: "alarms")
+
+ // Reload table view
+ if let table = AlarmViewController.staticTable { table.reloadData() }
+ }
+
+ /// Read alarms from local storage
+ func localRead() { list = JSON.parse([Alarm].self, localStorage.string(forKey: "alarms")!)! }
+
+ /// Read an alarm object from local storage
+ static func fromLocal() -> Alarms { return Alarms().apply { $0.localRead() } }
+
+ /// Get enabled alarms
+ var listEnabled: [Alarm] { return list.filter { $0.enabled } }
+
+ /// Get alarms that should be activating now
+ var listActivating: [Alarm]
+ {
+ let now = Date()
+ return listEnabled.filter { guard let n = $0.nextActivate else { return false }; return n < now }
+ }
+>>>>>>> Stashed changes
}