Guest User

Untitled

a guest
Jul 29th, 2018
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.70 KB | None | 0 0
  1. import java.io.FileInputStream
  2. import java.util.Locale
  3. import scala.io.Source.fromInputStream
  4. import java.io._
  5. import freemarker.template.{Template, TemplateExceptionHandler, Configuration}
  6. import org.apache.commons.dbcp.BasicDataSource
  7. import org.scala_tools.javautils.Implicits._
  8.  
  9. val DB_USER = "root"
  10. val DB_PASSWORD = ""
  11. val DB_URL = "jdbc:mysql://localhost:3306/fooDB"
  12.  
  13. case class CountyIncome(state:String, county:String, agi:Double,totalReturns:Double,averageReturn:Double) {
  14. def getAvgIncomeDisplay:String = {
  15. county + ", " + state + " " + "$%,2.2f".format(averageReturn*1000)
  16. }
  17. }
  18.  
  19. case class LLPoint(lat:Double, lon:Double)
  20.  
  21. case class KMLPlacemark(name:String, styleId:String, points:List[LLPoint], extrude:Int) {
  22. def jPoints:java.util.List[LLPoint] = {
  23. points.asJava
  24. }
  25. }
  26.  
  27. case object TemplateBuilder {
  28.  
  29. val fmEngine = getBaseFMConfig
  30.  
  31. def getBaseFMConfig = {
  32. val fmConfig = new Configuration
  33. fmConfig.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
  34. fmConfig.setLocale(Locale.US)
  35. fmConfig.setURLEscapingCharset("UTF-8")
  36. fmConfig.setNumberFormat("#########################");
  37. fmConfig
  38. }
  39.  
  40. def processTemplate(templateStr: String, model: java.util.Map[String, AnyRef]): String = {
  41. val t = new Template("name", new StringReader(templateStr), fmEngine)
  42. return processFMTemplate(t, model)
  43. }
  44.  
  45. private def processFMTemplate(fmTemplate: Template, model: java.util.Map[String, AnyRef]): String = {
  46. val sw = new StringWriter
  47. fmTemplate.process(model, sw)
  48. sw.toString
  49. }
  50. }
  51.  
  52. case class KMLStyle(id:String, color:String) {
  53. def getJID:java.lang.String = {
  54. id
  55. }
  56.  
  57. def getJColor:java.lang.String = {
  58. color
  59. }
  60. }
  61.  
  62.  
  63. // 0 is highest rank
  64.  
  65. /**
  66. * <color>
  67. Color and opacity (alpha) values are expressed in hexadecimal notation. The range of values for any one color is 0 to 255 (00 to ff).
  68. For alpha, 00 is fully transparent and ff is fully opaque. The order of expression is aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff);
  69. gg=green (00 to ff); rr=red (00 to ff). For example, if you want to apply a blue color with 50 percent opacity to an overlay,
  70. you would specify the following: <color>7fff0000</color>, where alpha=0x7f, blue=0xff, green=0x00, and red=0x00.
  71.  
  72. */
  73. def getColorFromRank(rank:Int, lowestRank:Int):Int = {
  74. // BLUE, GREEN, RED
  75. val opacity = 0xbf000000
  76. val lowRankColor = 0x000000FF
  77. val lowRankColorIncrement = 257
  78. val middleColor = 0x00ffffff
  79. val highRankColor = 0x0000ff00
  80.  
  81. // let's use green as highest, white middle, red worst
  82. // rank / lowestRank == x / 255; 255*rank = low*x, x=255*rank/low
  83. rank match {
  84. case redRank:Int if (rank >= lowestRank/2) => {
  85. val colorScale = 255*(redRank-(lowestRank/2)) / (lowestRank/2)
  86. val increment = 0x000101ff - 0x000000ff
  87. (0x7f0000ff + (increment * colorScale)) | (opacity)
  88.  
  89. }
  90. case greenRank:Int if (greenRank < lowestRank/2) => {
  91. // 00ff00 is the best, ffffff is worst, in this range
  92. // 00ff00 == 0, ffffff = lowRank / 2 OR
  93. // 00ff00
  94. // 01ff01
  95. // rank / lowRank/2 == x / 255; rank*255 == lowRank/2*x; x= rank*255 / lowRank/2
  96. val colorScale = 255*greenRank / (lowestRank/2)
  97. val increment = 0x01ff01 - 0x00ff00
  98. (0x0000ff00 + (increment * colorScale)) | (opacity)
  99. }
  100. }
  101.  
  102. }
  103.  
  104.  
  105.  
  106. /**
  107. * Given a county income, determine it's color for display in a map
  108. */
  109. def colorizeCounty( t:(Int,CountyIncome),lowRank:Int ):(Int,CountyIncome,Int) = {
  110. (t._1,t._2,getColorFromRank(t._1,lowRank))
  111. }
  112.  
  113.  
  114. def getDataSource(user:String, pass:String, url:String):BasicDataSource = {
  115. val ds = new BasicDataSource()
  116. ds.setDriverClassName("com.mysql.jdbc.Driver")
  117. ds.setUsername(user)
  118. ds.setPassword(pass)
  119. ds.setUrl(url)
  120. return ds
  121. }
  122.  
  123.  
  124. def getCountyPoints(county:CountyIncome):List[LLPoint] = {
  125. if (county.county.length <= 0) {
  126. return List[LLPoint]()
  127. }
  128.  
  129. //println("getting points for " + county.county + " and " + county.state)
  130. val con = getDataSource(DB_USER, DB_PASSWORD, DB_URL).getConnection
  131. val rset = con.createStatement.executeQuery("select latitude,longitude from counties where state=\"%s\" and county=\"%s\"".format(county.state,county.county))
  132. val pointList = new scala.collection.mutable.ListBuffer[LLPoint]()
  133. while (rset.next) {
  134. pointList += new LLPoint(rset.getDouble(1), rset.getDouble(2))
  135. }
  136. con.close
  137. //println("found point count " + pointList.size)
  138. return pointList.toList
  139. }
  140.  
  141.  
  142. def getFileAsString(name:String):String = {
  143. fromInputStream(new java.io.FileInputStream((new java.io.File(name)))).getLines.mkString
  144. }
  145.  
  146.  
  147. // ------------------------------------------------------------------------------------
  148. //
  149. // SCRIPT STARTS HERE
  150. //
  151. // ------------------------------------------------------------------------------------
  152.  
  153. // open the file containing county income data
  154. if (argv.size < 1) {
  155. println("scala income.scala <name of csv file>")
  156. System.exit(1)
  157. }
  158. val incomeFile = new java.io.File("countyincome07.csv")
  159. val incomeSource = fromInputStream(new FileInputStream(incomeFile))
  160.  
  161. // build a list of CountyIncome objects
  162. val incomeList = incomeSource.getLines.toList.tail.flatMap(line => {
  163. val parts = line.split(',')
  164.  
  165. parts.size match {
  166. case x if x >= 7 => List(new CountyIncome(parts(2).replace("\"",""), parts(3).replace("\"","").replace(" County","").trim, parts(6).toDouble, parts(4).toDouble, parts(6).toDouble / parts(4).toDouble))
  167. case _ => List()
  168. }
  169.  
  170. })
  171.  
  172. //val sortedIncomeList = incomeList.sort((L,R) => L.averageReturn > R.averageReturn).filter(x => x.state == "MO")
  173. val sortedIncomeList = incomeList.sort((L,R) => L.averageReturn > R.averageReturn)
  174. //println("sorted income list size " + sortedIncomeList.size)
  175. val rankedIncomeList = (1 to 5000).toList.zip(sortedIncomeList)
  176. val coloredRankedList = rankedIncomeList.map(x => colorizeCounty(x,rankedIncomeList.size))
  177. //println("colored list size " + coloredRankedList.size)
  178.  
  179. // build a list of styles with id and color, for the top of the KML
  180. val styleList = coloredRankedList.map(tup => KMLStyle("color_"+"%08X".format(tup._3), ""+"%08X".format(tup._3))).removeDuplicates
  181. //println("styleList size " + styleList.size)
  182.  
  183. // build a list of placemarks for each county
  184. val placemarks = coloredRankedList.map(tup => {
  185. System.err.println("working on rank " + tup._1)
  186. KMLPlacemark(tup._2.county + "," + tup._2.state,"color_"+"%08X".format(tup._3), getCountyPoints(tup._2), tup._1*1000)
  187. })
  188.  
  189. // now, using freemarker, build the KML
  190. val fmModel = Map[String,AnyRef]("placemarks" -> placemarks.asJava, "styles" -> styleList.asJava)
  191. val finalResult = TemplateBuilder.processTemplate(getFileAsString("incomeTemplate.ftl"), fmModel.asJava)
  192. println(finalResult)
  193.  
  194. //rankedIncomeList.filter(x => x._2.state == "CO" || x._2.state == "MO").foreach(x => println(x._1 + " " + x._2.getAvgIncomeDisplay))
Add Comment
Please, Sign In to add comment