@@ -157,3 +157,326 @@ extension Event: Entity {
157157 ]
158158 }
159159}
160+
161+ /// Campground Location
162+ public struct Campground : Equatable , Hashable , Codable , Identifiable {
163+
164+ public let id : UUID
165+
166+ public let created : Date
167+
168+ public let updated : Date
169+
170+ public var name : String
171+
172+ public var address : String
173+
174+ public var location : LocationCoordinates
175+
176+ public var amenities : [ Amenity ]
177+
178+ public var phoneNumber : String ?
179+
180+ public var descriptionText : String
181+
182+ /// The number of seconds from GMT.
183+ public var timeZone : Int
184+
185+ public var notes : String ?
186+
187+ public var directions : String ?
188+
189+ public var units : [ RentalUnit . ID ]
190+
191+ public var officeHours : Schedule
192+
193+ public init (
194+ id: UUID = UUID ( ) ,
195+ created: Date = Date ( ) ,
196+ updated: Date = Date ( ) ,
197+ name: String ,
198+ address: String ,
199+ location: LocationCoordinates ,
200+ amenities: [ Amenity ] = [ ] ,
201+ phoneNumber: String ? = nil ,
202+ descriptionText: String ,
203+ notes: String ? = nil ,
204+ directions: String ? = nil ,
205+ units: [ RentalUnit . ID ] = [ ] ,
206+ timeZone: Int = 0 ,
207+ officeHours: Schedule
208+ ) {
209+ self . id = id
210+ self . created = created
211+ self . updated = updated
212+ self . name = name
213+ self . address = address
214+ self . location = location
215+ self . amenities = amenities
216+ self . phoneNumber = phoneNumber
217+ self . descriptionText = descriptionText
218+ self . notes = notes
219+ self . directions = directions
220+ self . units = units
221+ self . timeZone = timeZone
222+ self . officeHours = officeHours
223+ }
224+
225+ public enum CodingKeys : CodingKey {
226+ case id
227+ case created
228+ case updated
229+ case name
230+ case address
231+ case location
232+ case amenities
233+ case phoneNumber
234+ case descriptionText
235+ case timeZone
236+ case notes
237+ case directions
238+ case units
239+ case officeHours
240+ }
241+ }
242+
243+ extension Campground : Entity {
244+
245+ public static var entityName : EntityName { " Campground " }
246+
247+ public static var attributes : [ CodingKeys : AttributeType ] {
248+ [
249+ . name : . string,
250+ . created : . date,
251+ . updated : . date,
252+ . address : . string,
253+ . location: . string,
254+ . amenities: . string,
255+ . phoneNumber: . string,
256+ . descriptionText: . string,
257+ . timeZone: . int32,
258+ . notes: . string,
259+ . directions: . string,
260+ . officeHours: . string
261+ ]
262+ }
263+
264+ public static var relationships : [ CodingKeys : Relationship ] {
265+ [
266+ . units : Relationship (
267+ id: PropertyKey ( CodingKeys . units) ,
268+ type: . toMany,
269+ destinationEntity: RentalUnit . entityName,
270+ inverseRelationship: PropertyKey ( RentalUnit . CodingKeys. campground)
271+ )
272+ ]
273+ }
274+ }
275+
276+ public extension Campground {
277+
278+ /// Campground Amenities
279+ enum Amenity : String , Codable , CaseIterable {
280+
281+ case water
282+ case amp30
283+ case amp50
284+ case wifi
285+ case laundry
286+ case mail
287+ case dumpStation
288+ case picnicArea
289+ case storage
290+ case cabins
291+ case showers
292+ case restrooms
293+ case pool
294+ case fishing
295+ case beach
296+ case lake
297+ case river
298+ case rv
299+ case tent
300+ case pets
301+ }
302+ }
303+
304+ extension Array : AttributeEncodable where Self. Element == Campground . Amenity {
305+
306+ public var attributeValue : AttributeValue {
307+ let string = self . reduce ( " " , { $0 + ( $0. isEmpty ? " " : " , " ) + $1. rawValue } )
308+ return . string( string)
309+ }
310+ }
311+
312+ extension Array : AttributeDecodable where Self. Element == Campground . Amenity {
313+
314+ public init ? ( attributeValue: AttributeValue ) {
315+ guard let string = String ( attributeValue: attributeValue) else {
316+ return nil
317+ }
318+ let components = string
319+ . components ( separatedBy: " , " )
320+ . filter { $0. isEmpty == false }
321+ var values = [ Campground . Amenity] ( )
322+ values. reserveCapacity ( components. count)
323+ for element in components {
324+ guard let value = Self . Element ( rawValue: element) else {
325+ return nil
326+ }
327+ values. append ( value)
328+ }
329+ self = values
330+ }
331+ }
332+
333+ public extension Campground {
334+
335+ /// Location Coordinates
336+ struct LocationCoordinates : Equatable , Hashable , Codable {
337+
338+ /// Latitude
339+ public var latitude : Double
340+
341+ /// Longitude
342+ public var longitude : Double
343+
344+ public init ( latitude: Double , longitude: Double ) {
345+ self . latitude = latitude
346+ self . longitude = longitude
347+ }
348+ }
349+ }
350+
351+ extension Campground . LocationCoordinates : AttributeEncodable {
352+
353+ public var attributeValue : AttributeValue {
354+ return . string( " \( latitude) , \( longitude) " )
355+ }
356+ }
357+
358+ extension Campground . LocationCoordinates : AttributeDecodable {
359+
360+ public init ? ( attributeValue: AttributeValue ) {
361+ guard let string = String ( attributeValue: attributeValue) else {
362+ return nil
363+ }
364+ let components = string. components ( separatedBy: " , " )
365+ guard components. count == 2 ,
366+ let latitude = Double ( components [ 0 ] ) ,
367+ let longitude = Double ( components [ 1 ] ) else {
368+ return nil
369+ }
370+ self . init ( latitude: latitude, longitude: longitude)
371+ }
372+ }
373+
374+ public extension Campground {
375+
376+ /// Schedule (e.g. Check in, Check Out)
377+ struct Schedule : Equatable , Hashable , Codable {
378+
379+ public var start : UInt
380+
381+ public var end : UInt
382+
383+ public init ( start: UInt , end: UInt ) {
384+ assert ( start < end)
385+ self . start = start
386+ self . end = end
387+ }
388+ }
389+ }
390+
391+ extension Campground . Schedule : AttributeEncodable {
392+
393+ public var attributeValue : AttributeValue {
394+ return . string( " \( start) , \( end) " )
395+ }
396+ }
397+
398+ extension Campground . Schedule : AttributeDecodable {
399+
400+ public init ? ( attributeValue: AttributeValue ) {
401+ guard let string = String ( attributeValue: attributeValue) else {
402+ return nil
403+ }
404+ let components = string. components ( separatedBy: " , " )
405+ guard components. count == 2 ,
406+ let start = UInt ( components [ 0 ] ) ,
407+ let end = UInt ( components [ 1 ] ) else {
408+ return nil
409+ }
410+ self . init ( start: start, end: end)
411+ }
412+ }
413+
414+ public extension Campground {
415+
416+ /// Campground Rental Unit
417+ struct RentalUnit : Equatable , Hashable , Codable , Identifiable {
418+
419+ public let id : UUID
420+
421+ public let campground : Campground . ID
422+
423+ public var name : String
424+
425+ public var notes : String ?
426+
427+ public var amenities : [ Amenity ]
428+
429+ public var checkout : Schedule
430+
431+ public init (
432+ id: UUID = UUID ( ) ,
433+ campground: Campground . ID ,
434+ name: String ,
435+ notes: String ? = nil ,
436+ amenities: [ Amenity ] = [ ] ,
437+ checkout: Schedule
438+ ) {
439+ self . id = id
440+ self . campground = campground
441+ self . name = name
442+ self . notes = notes
443+ self . amenities = amenities
444+ self . checkout = checkout
445+ }
446+
447+ public enum CodingKeys : CodingKey {
448+
449+ case id
450+ case campground
451+ case name
452+ case notes
453+ case amenities
454+ case checkout
455+ }
456+ }
457+ }
458+
459+ extension Campground . RentalUnit : Entity {
460+
461+ public static var entityName : EntityName { " RentalUnit " }
462+
463+ public static var attributes : [ CodingKeys : AttributeType ] {
464+ [
465+ . name : . string,
466+ . notes : . string,
467+ . amenities : . string,
468+ . checkout : . string
469+ ]
470+ }
471+
472+ public static var relationships : [ CodingKeys : Relationship ] {
473+ [
474+ . campground : Relationship (
475+ id: PropertyKey ( CodingKeys . campground) ,
476+ type: . toOne,
477+ destinationEntity: Campground . entityName,
478+ inverseRelationship: PropertyKey ( Campground . CodingKeys. units)
479+ )
480+ ]
481+ }
482+ }
0 commit comments