private def initCategoryList: IndexedSeq[(Double, Double)] = { val ret = new ArrayBuffer[(Double, Double)]() var catsLeft = ncats if (min != vll.green) { ret += ((roundify(min), roundify(vll.green))) catsLeft -= 1 } val width = (max - vll.green) / catsLeft val distances = Array[Double](vll.yellow - vll.green, vll.red - vll.yellow, vll.darkred - vll.red, max - vll.darkred) val preCatsList = distances map(distance => (distance, distance/width, Math.round(distance / width).toInt)) val preCatsPlusFraction = preCatsList map(cat => (cat._1, cat._2, cat._3, (cat._3 > cat._2) match { case true => cat._2 + 1.0 - cat._3 case false => cat._2 - cat._3 })) // tuple (distance, double cats, rounded cats, fraction) val preCatsCount = preCatsPlusFraction.map(_._3).reduce((a, b) => a + b) var finalCats: Array[(Double, Double, Int, Double)] = null val defect = catsLeft - preCatsCount defect match { case 0 => finalCats = preCatsPlusFraction //do nothing, preCatsCount are already correct case 1 => { val (fractionMax, maxCount) = preCatsPlusFraction.filter(_._3 > 1).map(x => (x._4, 1)).reduce((a, b) => { val maxFraction = Math.max(a._1, b._1) val count = (a._1 - b._1) match { case 0 => a._2 + b._2 case x => if (x > 0) a._2 else b._2 } (maxFraction, count) }) var index = 0 maxCount match { case 1 => { index = preCatsPlusFraction.zipWithIndex.find(_._1._4 == fractionMax).get._2 } case _ => { index = preCatsPlusFraction.zipWithIndex.filter(_._1._4 == fractionMax).reduce((a, b) => { (a._1._3 < b._1._3) match { case true => b case false => a } })._2 } } finalCats = preCatsPlusFraction.zipWithIndex.map(x => x._2 == index match { case true => (x._1._1, x._1._2, x._1._3 + 1, x._1._4) case false => x._1 }) } case -1 => { var (fractionMin, minCount) = preCatsPlusFraction.filter(_._3 > 1).map(x => (x._4, 1)).reduce((a, b) => { val minFraction = Math.min(a._1, b._1) val count = (a._1 - b._1) match { case 0 => a._2 + b._2 case x => if (x > 0) b._2 else a._2 } (minFraction, count) }) var index = 0 minCount match { case 1 => { index = preCatsPlusFraction.zipWithIndex.find(_._1._4 == fractionMin).get._2 } case _ => { index = preCatsPlusFraction.zipWithIndex.filter(_._1._4 == fractionMin).reduce((a, b) => { (a._1._3 < b._1._3) match { case true => b case false => a } })._2 } } finalCats = preCatsPlusFraction.zipWithIndex.map(x => x._2 == index match { case true => (x._1._1, x._1._2, x._1._3 - 1, x._1._4) case false => x._1 }) } case -2 => { // this is very unlikely to happen var indices = preCatsPlusFraction.zipWithIndex.filter(x=> x._1._3 > 1).sortWith((a, b) => a._1._4 < b._1._4 || (a._1._4 == b._1._4 && a._1._3 > b._1._3)).slice(0, 2).map(_._2) finalCats = preCatsPlusFraction.zipWithIndex.map(x => indices.contains(x._2) match { case true => (x._1._1, x._1._2, x._1._3 -1, x._1._4) case false => x._1 }) } case _ => throw new RuntimeException("Problem with building LinearDoubleCategory") } val catsWithLevels = finalCats.zipWithIndex.map(x => { x._2 match { case 0 => (x._1, vll.green) case 1 => (x._1, vll.yellow) case 2 => (x._1, vll.red) case 3 => (x._1, vll.darkred) } }) for (x <- catsWithLevels) { var tmp = x._2 val colorWidth = x._1._1 / x._1._3 for (i <- 0 until x._1._3 - 1) { ret += ((roundify(tmp + colorWidth * i), roundify(tmp + colorWidth * (i + 1)))) } if (x._1._3 > 0) ret += ((roundify(tmp + colorWidth * Math.max(x._1._3 - 1, 0)), roundify(tmp + x._1._1))) } ret }