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