{"version":3,"sources":["https://lively-kernel.org/lively4/BP2019RH-stable/src/internal/individuals-as-points/map/dataHandler.js"],"names":["GroupingAction","DataHandler","constructor","geoData","individuals","pointSize","canvasWidth","canvasHeight","featureToAVFLookup","missingDataKeys","locationGroupingAttribute","locationLookupKey","colorToIndividualId","individualsGroupedByDistrict","groupIndividualsByDistrict","themeToAmount","themeToAmountInDistrict","selectedThemes","setColorStore","colorStore","setIndividuals","forEach","individual","color","drawing","identifyingColor","colorString","r","g","b","id","initializeIndividuals","position","calculateIndividualsPosition","imageData","path","districtCount","length","missingGroups","Object","keys","key","missingFeatureMatches","districtName","getDistrictLookupName","individualsInDistrict","push","population","count","previousCount","gridDensity","points","districtColor","districtToColor","properties","bounds","boundingArea","area","boundsToAreaRatio","squareArea","edgeLength","Math","sqrt","offset","j","i","testSquareColor","slice","setIndividualPosition","x","y","w","topLeft","testPixelColor","topRight","bottomLeft","bottomRight","center","index","round","data","action","setAttribute","runOn","feature","lookupName","toLowerCase","addDistrictsForMissingData","missingDataFeatureToTextCoordinates","missingDataFeature","coordinates","getCoordinatesForMissingFeature","geometry","createDistrictColorCoding","colorToDistrict","parseInt","setSelectedIndividual","selectedIndividual","SomaliaDataHandler","getIndividualThemes","themes","getIndividualDistrict","district","KenyaDataHandler","concat","county"],"mappings":"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","file":"dataHandler.js","sourcesContent":["import { GroupingAction } from \"../../../../prototypes/display-exploration/actions.js\"\n\nexport class DataHandler {\n  \n  constructor(geoData, individuals, pointSize, canvasWidth, canvasHeight, featureToAVFLookup, missingDataKeys, locationGroupingAttribute, locationLookupKey) {\n    this.geoData = geoData\n    this.individuals = individuals\n    this.colorToIndividualId = {}\n    this.canvasWidth = canvasWidth\n    this.canvasHeight = canvasHeight\n    this.featureToAVFLookup = featureToAVFLookup\n    this.missingDataKeys = missingDataKeys\n    this.locationGroupingAttribute = locationGroupingAttribute\n    this.locationLookupKey = locationLookupKey\n    this.individualsGroupedByDistrict = this.groupIndividualsByDistrict()\n    this.themeToAmount = {}\n    this.themeToAmountInDistrict = {}\n    this.selectedThemes = null\n    this.pointSize = pointSize\n  }\n  \n  setColorStore(colorStore) {\n    this.colorStore = colorStore\n  }\n  \n  setIndividuals(individuals) {\n    this.individuals = individuals\n    this.individualsGroupedByDistrict = this.groupIndividualsByDistrict()\n    this.individuals.forEach((individual) => {\n      let color = individual.drawing.identifyingColor\n      let colorString = \"r\" + color.r + \"g\" + color.g + \"b\" + color.b\n      this.colorToIndividualId[colorString] = individual.id\n    })\n  }\n  \n  initializeIndividuals() {\n    this.individuals.forEach((individual) => {\n      let color = individual.drawing.identifyingColor\n      let colorString = \"r\" + color.r + \"g\" + color.g + \"b\" + color.b\n      this.colorToIndividualId[colorString] = individual.id\n      // TODO: use defaultPosition from dataprocessor scheme\n      individual.drawing.position = {}\n    })\n  }\n  \n  calculateIndividualsPosition(imageData, path) {\n    let districtCount = this.geoData.length\n    var missingGroups = {}\n    Object.keys(this.individualsGroupedByDistrict).forEach(key => {\n      missingGroups[key] = 1\n    })\n    var missingFeatureMatches = []\n    while(districtCount--){\n      let districtName = this.getDistrictLookupName(this.geoData[districtCount])\n      let individualsInDistrict = this.individualsGroupedByDistrict[districtName]      \n      \n      if(!individualsInDistrict) {\n        missingFeatureMatches.push(districtName)\n        continue\n      }\n      \n      let population = individualsInDistrict.length\n      delete missingGroups[districtName]\n      if ( !population ) {\n        continue\n      }\n      let count = 0\n      let previousCount = 0\n      let gridDensity = 1\n      let points = []\n      let districtColor = this.districtToColor[this.geoData[districtCount].properties[this.locationLookupKey]]\n      let r = districtColor.r, g = districtColor.g, b = districtColor.b\n      \n      let bounds = path.bounds(this.geoData[districtCount])\n      let boundingArea = (bounds[1][0] - bounds[0][0]) * (bounds[1][1] - bounds[0][1])\n      let area = path.area(this.geoData[districtCount])\n      let boundsToAreaRatio = boundingArea / area\n      let squareArea = area / population\n      let edgeLength = Math.sqrt(squareArea / boundsToAreaRatio) / gridDensity\n      let offset = Math.sqrt(area) / 15\n      \n      //console.log(this.geoData[districtCount].properties[this.locationLookupKey])\n      //console.log(\"BoundingArea, Area, ratio, squareArea, edgelength: \", boundingArea, area, boundsToAreaRatio, squareArea, edgeLength)\n      \n      \n      while (count < population) {\n        count = 0\n        points = []\n        \n        edgeLength = Math.sqrt(squareArea / Math.sqrt(boundsToAreaRatio)) / gridDensity\n\n        // TODO: error handling when districtColor is not defined (should not happen)\n        for (let j = bounds[0][1]; j < bounds[1][1]; j += edgeLength) {\n          for (let i = bounds[0][0]; i < bounds[1][0]; i += edgeLength) {\n            if (this.testSquareColor(imageData, i, j, this.canvasWidth, r, g, b, offset)) {\n              points.push([i, j])\n              count++\n            }\n          }\n        }\n        \n        /*if (gridDensity === 1) {\n          console.log(\"First grid count: \", count, population)\n        }*/\n        \n        if (count === previousCount) {\n          gridDensity += 0.5\n        } else {\n          gridDensity += 0.1\n        }\n        previousCount = count\n      }\n      points = points.slice(0, population)\n      for (let i = 0; i < points.length; i++) {\n        this.setIndividualPosition(individualsInDistrict[i], points[i][0],points[i][1])\n      }\n    }\n  }\n  \n  testSquareColor(imageData, x, y, w, r, g, b, offset) {\n    let topLeft = this.testPixelColor(imageData, x - offset, y - offset, w, r, g, b)\n    let topRight = this.testPixelColor(imageData, x + offset, y - offset, w, r, g, b)\n    let bottomLeft = this.testPixelColor(imageData, x - offset, y + offset, w, r, g, b)\n    let bottomRight = this.testPixelColor(imageData, x + offset, y + offset, w, r, g, b)\n    let center = this.testPixelColor(imageData, x, y, w, r, g, b)\n    return topLeft && topRight && bottomLeft && bottomRight && center\n  }\n\n  testPixelColor(imageData, x, y, w, r, g, b){    \n    if (y < 0 || x < 0) {\n      debugger\n      return true\n    }\n    let index = (Math.round(x) + Math.round(y) * w) * 4\n    return imageData.data[index] == r && imageData.data[index + 1] == g && imageData.data[index + 2] == b\n  }\n\n  setIndividualPosition(individual, x, y) {\n    individual.drawing.position.x = x\n    individual.drawing.position.y = y\n  }\n  \n  groupIndividualsByDistrict() {\n    let action = new GroupingAction()\n    action.setAttribute(this.locationGroupingAttribute)\n    let individualsGroupedByDistrict = action.runOn(this.individuals)\n    return individualsGroupedByDistrict\n  }\n\n  getDistrictLookupName(feature) {\n    let lookupName = this.featureToAVFLookup[feature.properties[this.locationLookupKey]]\n    if (lookupName) {\n      return lookupName\n    } else {\n      lookupName = feature.properties[this.locationLookupKey].toLowerCase()\n      return lookupName\n    }\n  }\n  \n  addDistrictsForMissingData() {\n    this.missingDataFeatureToTextCoordinates = {}\n    let j = 1\n    this.missingDataKeys.forEach(key => {\n      let missingDataFeature = {\"type\" : \"Feature\", \"properties\" : {}, \"geometry\" : {\"type\" : \"MultiPolygon\", \"coordinates\" : []}\n      }\n      let coordinates = this.getCoordinatesForMissingFeature(j)\n      missingDataFeature.geometry.coordinates = [[coordinates]]\n      missingDataFeature.properties[this.locationLookupKey] = key\n      this.geoData.push(missingDataFeature)\n      j += 1.5\n      this.missingDataFeatureToTextCoordinates[key] = [coordinates[0][0], coordinates[0][1] + 0.1]\n    })\n  }\n    \n  createDistrictColorCoding() {\n    this.colorToDistrict = {}\n    this.districtToColor = {}\n    let i = this.geoData.length\n    while(i--){\n      let r = parseInt((i + 1) / 256)\n      let g = (i + 1) % 256\n      let b = 10*(i + 1) % 256\n      this.colorToDistrict[\"rgb(\" + r + \",\" + g + \",\" + b + \")\"] = this.geoData[i]\n      this.districtToColor[this.geoData[i].properties[this.locationLookupKey]] = {\"r\": r, \"g\": g, \"b\": b, \"opacity\": 1}\n    }\n  }\n  \n  setSelectedIndividual(individual) {\n    this.selectedIndividual = individual\n  }\n}\n\nexport class SomaliaDataHandler extends DataHandler {\n  getCoordinatesForMissingFeature(j) {\n    return [[47.7,1.3+j],\n              [51.8,1.3+j],\n              [51.8,-1.7+j],\n              [47.7,-1.7+j],\n              [47.7,1.3+j]]\n  }\n  \n  getIndividualThemes(individual) {\n    return individual.themes\n  }\n  \n  getIndividualDistrict(individual) {\n    return individual.district\n  }\n}\n\nexport class KenyaDataHandler extends DataHandler {\n  getCoordinatesForMissingFeature(j){\n    return [[31,-3.5+j],\n              [35,-3.5+j],\n              [35,-6.5+j],\n              [31,-6.5+j],\n              [31,-3.5+j]]\n  }\n  \n  getIndividualThemes(individual) {\n    return individual.themes[\"L1\"].concat(individual.themes[\"L2\"]).concat(individual.themes[\"L3\"])\n  }\n  \n  getIndividualDistrict(individual) {\n    return individual.county\n  }\n}"]}