pyc-website

main website for pyc inc.

git clone https://9o.is/git/pyc-website.git

Atm.scala

(5501B)


      1 package inc.pyc
      2 package model
      3 
      4 import lib._
      5 import field._
      6 import net.liftweb._
      7 import common.{Box, Empty}
      8 import util.Helpers
      9 import json._
     10 import JsonDSL._
     11 import mongodb.record._
     12 import mongodb.record.field._
     13 import record.field.{StringField, PostalCodeField, CountryField, Countries, TimeZoneField}
     14 import com.foursquare.rogue._
     15 import org.joda.time._, format._
     16 import net.liftmodules.mongoauth.field._
     17 import org.bson.types.ObjectId
     18 
     19 class Atm private () extends MongoRecord[Atm] with ObjectIdPk[Atm] {
     20   def meta = Atm
     21   
     22   object name extends StringField(this, 64)
     23   object address extends StringField(this, 255)
     24   object city extends StringField(this, 64)
     25   object state extends StringField(this, 64)
     26   object postal extends PostalCodeField(this, country)
     27   object phone extends StringField(this, 64)
     28   object owner extends StringField(this, 64)
     29   object website extends StringField(this, 255)
     30   object model extends StringField(this, 64)
     31   object times extends BsonRecordListField(this, TimeOpen)
     32   object ownerObj extends ObjectIdRefField(this, User)
     33   
     34   object country extends CountryField(this) {
     35     override def defaultValue = Countries.USA
     36   }
     37   
     38   object timezone extends TimeZoneField(this)
     39   
     40   /**
     41    * This is used for the ATM to authenticate and communicate with the web server.
     42    */
     43   object secret extends PasswordField(this, 32, 32)
     44   
     45   /** The Geolocation of the atm. */
     46   object loc extends MongoCaseClassField[Atm, LatLong](this) {
     47     import Geocode._
     48     
     49     def apply(geo: GeoPoint): Atm = {
     50       val latLong = LatLong(geo.lat, geo.lng)
     51       apply(latLong)
     52     }
     53   }
     54   
     55   override def asJValue: JObject = {
     56     val json = super.asJValue merge
     57       ("status" -> status) ~ 
     58       ("statusLevel" -> statusLevel)
     59     
     60     (json transform {
     61       case JField("lat", lat) => JField("latitude", lat)
     62       case JField("long", lng) => JField("longitude", lng)
     63       case JField("secret", _) => JField("secret", "")
     64       case JField("ownerObj", _) => JField("ownerObj", "")
     65       case JField("_id", _) => JField("_id", "")
     66     })
     67     .asInstanceOf[JObject]
     68   }
     69   
     70   
     71   private def timeForToday: TimeOpen = {
     72     val now = DateTime.now
     73     
     74     val today = {
     75       val n = now.dayOfWeek.get
     76       if(n==7) 0 else n // DateTime's Sunday is 7, but TimeOpen's Sunday is 0
     77     }
     78     
     79     times.get(today)
     80   }
     81   
     82   /**
     83    * Whether the ATM is available for service or not.
     84    */
     85   private def isOpen: Boolean = {
     86     val comparator = DateTimeComparator.getTimeOnlyInstance()
     87     val formatter = DateTimeFormat.forPattern("HH:mm ZZZ")
     88     val time = timeForToday
     89     val now = DateTime.now.withZone(DateTimeZone.forID(timezone.get))
     90     val open = formatter.parseDateTime(time.open.get + " " + timezone.get)
     91     val close = formatter.parseDateTime(time.close.get + " " + timezone.get)
     92     
     93     (comparator.compare(now, open) == 1) && (comparator.compare(now, close) == -1)
     94   }
     95   
     96   private def status = if(isOpen) "Now Open" else "Now Closed"
     97   private def statusLevel = if(isOpen) "success" else "warning"
     98 }
     99 
    100 object Atm extends Atm with RogueMetaRecord[Atm] {
    101   import mongodb.BsonDSL._
    102   import Geocode._
    103   
    104   override def collectionName = "atm.atms"
    105     
    106   ensureIndex((name.name -> 1), unique = true)
    107   ensureIndex(loc.name -> "2d", unique = true)
    108   
    109   def findByName(in: String): Box[Atm] = find(name.name, in)
    110   
    111   def findByStringId(id: String): Box[Atm] =
    112     if (ObjectId.isValid(id)) find(new ObjectId(id))
    113     else Empty
    114   
    115   /**
    116    * Searches for ATM's within a certain distance from a geolocation.
    117    */
    118   def nearby(geo: GeoPoint, kilometers: Double) = {
    119     val radius = Degrees((kilometers / 6378.137).toDegrees)
    120     this.where(_.loc near (geo.lat, geo.lng, radius)).fetch()
    121   }
    122 }
    123 
    124 
    125 /**
    126  * Range of time open for one day.
    127  */
    128 class TimeOpen private () extends BsonRecord[TimeOpen] {
    129   def meta = TimeOpen
    130   
    131   /* Open/Close format HH:mm */
    132   object open extends StringField(this, 10)
    133   object close extends StringField(this, 10)
    134 }
    135 
    136 object TimeOpen extends TimeOpen with BsonMetaRecord[TimeOpen] {
    137   def create(open: String, close: String) = 
    138     TimeOpen.createRecord.open(open).close(close)
    139 }
    140 
    141 object FeaturedAtm {
    142   import TimeOpen._
    143   
    144   val name = "Crispins"
    145 
    146   lazy val atm: Atm = Atm.findByName(name) openOr {
    147     
    148     val ownerEmail = "robertetaylor@gmail.com"
    149     val ownerUser = "Robert_Taylor"
    150     val ownerFname = "Robert"
    151     val ownerLname = "Taylor"
    152       
    153     val owner: User = User.findByEmail(ownerEmail) openOr {
    154       User.createRecord
    155         .email(ownerEmail)
    156         .username(ownerUser)
    157         .fname(ownerFname)
    158         .lname(ownerLname)
    159         .roles("atm_owner" :: Nil)
    160         .password(Helpers.randomString(20), true)
    161         .save()
    162     }
    163  
    164     val times = 
    165         create("12:00", "2:00") ::
    166         create("12:00", "2:00") ::
    167         create("12:00", "2:00") ::
    168         create("12:00", "2:00") ::
    169         create("12:00", "2:00") ::
    170         create("12:00", "2:00") ::
    171         create("12:00", "2:00") :: Nil
    172     
    173     Atm.createRecord
    174       .name(name)
    175       .secret("$2a$10$F/91Ve4n16NkgDT7GQgQUuTjDkQdxV.U1lDAPdQs5LIsbH44FB/ci")
    176       .loc(LatLong(40.765708, -73.990707))
    177       .address("764 10th Ave")
    178       .city("New York")
    179       .state("New York")
    180       .postal("10019")
    181       .phone("(212) 586-0888")
    182       .owner(ownerFname + " " + ownerLname)
    183       .ownerObj(owner.id.get)
    184       .website("http://www.crispinsnyc.com")
    185       .model("skyhook")
    186       .timezone("America/New_York")
    187       .times(times)
    188       .save()
    189   }
    190 }