<commit_before>angular.module('app').directive 'appRadar', ['$log', '$timeout', ($log, $timeout) ->
  restrict: 'E'
  templateUrl: '/views/directives/techRadar.html'
  transclude: true
  controller: ['$scope', '$element', '$attrs', '$location', ($scope, $element, $attrs, $location) ->
    $scope.hello = "hello world"
  ]
  link: (scope, element) ->
    scope.controls = []

    defineControl = (name, initializationParameter, integerType, min, max, initialValue, updateCallback) ->
      if(initialValue < min || initialValue > max)
        throw new Error("Initial value must be between min and max")

      redraw = () ->
        ### clear the elements inside of the directive ###
        vis.selectAll('*').remove();
        force.stop()
        drawRadar()

      position = scope.controls.push({name: name, initParam: initializationParameter, min: min, max: max, value: initialValue, integerType: integerType}) - 1
      boundControl = _.bind((newValue)->
        if newValue
          this.value = newValue
          if updateCallback
            updateCallback(newValue)
          if this.initParam
            redraw()
          scope.$apply()
        this.value
      , scope.controls[position])
      scope.controls[position].update = boundControl

      boundControl

    data = [
      # Slices
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
    ]

    initialNumSlices = data.length
    initialNumRings = Math.max(_.keys(_.countBy(data, (slice) -> return slice.length )))

    numSlices = defineControl("Number of slices", true, true, initialNumSlices, 4, initialNumSlices)
    numRings = defineControl("Number of rings", true, true, initialNumRings, 5, initialNumRings)
    slowMo = defineControl("Slow-mo", false, true, 0, 1000, 0)

    _.each(ring, (d) ->
        d.slice = i_s
        d.ring = i_r
      , slice
    ) for ring, i_r in slice for slice, i_s in data

    nodes = _.flatten(data)
    radii = []
    arcs = []

    baseWidth = defineControl("Base ring width", true, false, 10, 500, 180)
    radiusSoftener = defineControl("Radius softener", true, false, 1, 1.01, 1.003)
    nodeRadius = defineControl("Node radius", false, true, 1, 30, 8)


    getOuterRadiusForSameArea = (commonRadius, innerRadius) ->
      Math.pow(Math.sqrt(2*commonRadius*commonRadius - innerRadius*innerRadius), radiusSoftener())

    defineRing = (ring) ->
      innerR = (if ring==0 then 0 else radii[ring-1].outer)
      outerR = (if ring==0 then baseWidth() else getOuterRadiusForSameArea(innerR, radii[ring-1].inner))
      radii.push({inner: innerR, outer: outerR})

    defineArc = (slice, ring) ->
      radialWidthDeg = 360/numSlices()
      startAngleDeg = slice * radialWidthDeg
      endAngleDeg = startAngleDeg + radialWidthDeg
      arcs.push({slice: slice, ring: ring, innerRadius: radii[ring].inner, outerRadius: radii[ring].outer, startAngle: startAngleDeg, endAngle: endAngleDeg, data: data[slice][ring]})

    getArc = (node) ->
      index = node.ring + node.slice * numRings()
      arcs[index]

    pi = Math.PI
    degToRads = pi/180

    arcTemplate = d3.svg.arc().innerRadius((d) -> d.innerRadius).outerRadius((d) -> d.outerRadius).startAngle((d) -> d.startAngle * degToRads).endAngle((d) -> d.endAngle * degToRads)

    getArcPosition = (node) ->
      arcTemplate.centroid(getArc(node))

    layoutWidth = defineControl("Layout width", true, true, 0, 960, 960)
    layoutHeight = defineControl("Layout height", true, true, 0, 1200, 700)
    padding = defineControl("Node padding", true, false, 0, 15, 6)

    forceGravity = defineControl("Gravity", false, false, 0, 1, 0, (g) -> masterForce.gravity(g))
    forceAlpha = defineControl("Alpha", false, false, 0, 3, 0.2, (a) -> masterForce.alpha(a))
    forceCharge = defineControl("Charge", false, false, -50, 50, -2, (c) -> masterForce.charge(c))
    forceFriction = defineControl("Friction", false, false, .8, 1, .90, (f) -> masterForce.friction(f))

    forces = []

    masterForce = {
      gravity: (g) -> _.each(forces, (force) -> force.gravity(g)); this
      alpha: (a) -> _.each(forces, (force) -> force.alpha(a)); this
      charge: (c) -> _.each(forces, (force) -> force.charge(c)); this
      friction: (f) -> _.each(forces, (force) -> force.friction(f)); this
      resume: () ->  _.each(forces, (force) -> force.resume()); this
      start: () ->  _.each(forces, (force) -> force.start()); this
      apply: (func) ->  _.each(forces, (force) -> func(force)); this<commit_msg>Force layout per-arc and better tuning<commit_after>angular.module('app').directive 'appRadar', ['$log', '$timeout', ($log, $timeout) ->
  restrict: 'E'
  templateUrl: '/views/directives/techRadar.html'
  transclude: true
  controller: ['$scope', '$element', '$attrs', '$location', ($scope, $element, $attrs, $location) ->
    $scope.hello = "hello world"
  ]
  link: (scope, element) ->
    scope.controls = []

    defineControl = (name, initializationParameter, integerType, min, max, initialValue, updateCallback) ->
      if(initialValue < min || initialValue > max)
        throw new Error("Initial value must be between min and max")

      redraw = () ->
        ### clear the elements inside of the directive ###
        vis.selectAll('*').remove();
        force.stop()
        drawRadar()

      position = scope.controls.push({name: name, initParam: initializationParameter, min: min, max: max, value: initialValue, integerType: integerType}) - 1
      boundControl = _.bind((newValue)->
        if newValue
          this.value = newValue
          if updateCallback
            updateCallback(newValue)
          if this.initParam
            redraw()
          scope.$apply()
        this.value
      , scope.controls[position])
      scope.controls[position].update = boundControl

      boundControl

    data = [
      # Slices
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
      [
        # Rings
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
        [
          {label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'something'},{label: 'last'}
        ]
      ]
    ]

    initialNumSlices = data.length
    initialNumRings = Math.max(_.keys(_.countBy(data, (slice) -> return slice.length )))

    numSlices = defineControl("Number of slices", true, true, initialNumSlices, 4, initialNumSlices)
    numRings = defineControl("Number of rings", true, true, initialNumRings, 5, initialNumRings)
    slowMo = defineControl("Slow-mo", false, true, 0, 1000, 0)

    _.each(ring, (d) ->
        d.slice = i_s
        d.ring = i_r
      , slice
    ) for ring, i_r in slice for slice, i_s in data

    nodes = _.flatten(data)
    radii = []
    arcs = []

    baseWidth = defineControl("Base ring width", true, false, 10, 500, 180)
    radiusSoftener = defineControl("Radius softener", true, false, 1, 1.01, 1.003)
    nodeRadius = defineControl("Node radius", false, true, 1, 30, 8)


    getOuterRadiusForSameArea = (commonRadius, innerRadius) ->
      Math.pow(Math.sqrt(2*commonRadius*commonRadius - innerRadius*innerRadius), radiusSoftener())

    defineRing = (ring) ->
      innerR = (if ring==0 then 0 else radii[ring-1].outer)
      outerR = (if ring==0 then baseWidth() else getOuterRadiusForSameArea(innerR, radii[ring-1].inner))
      radii.push({inner: innerR, outer: outerR})

    defineArc = (slice, ring) ->
      radialWidthDeg = 360/numSlices()
      startAngleDeg = slice * radialWidthDeg
      endAngleDeg = startAngleDeg + radialWidthDeg
      arcs.push({slice: slice, ring: ring, innerRadius: radii[ring].inner, outerRadius: radii[ring].outer, startAngle: startAngleDeg, endAngle: endAngleDeg, data: data[slice][ring]})

    getArc = (node) ->
      index = node.ring + node.slice * numRings()
      arcs[index]

    pi = Math.PI
    degToRads = pi/180

    arcTemplate = d3.svg.arc().innerRadius((d) -> d.innerRadius).outerRadius((d) -> d.outerRadius).startAngle((d) -> d.startAngle * degToRads).endAngle((d) -> d.endAngle * degToRads)

    getArcPosition = (node) ->
      arcTemplate.centroid(getArc(node))

    layoutWidth = defineControl("Layout width", true, true, 0, 960, 960)
    layoutHeight = defineControl("Layout height", true, true, 0, 1200, 700)
    padding = defineControl("Node padding", true, false, 0, 15, 6)

    forceGravity = defineControl("Gravity", false, false, 0, 1, 0, (g) -> masterForce.gravity(g))
    forceAlpha = defineControl("Alpha", false, false, 0, 3, 0.2, (a) -> masterForce.alpha(a))
    forceCharge = defineControl("Charge", false, false, -50, 50, -2, (c) -> masterForce.charge(c))
    forceFriction = defineControl("Friction", false, false, .8, 1, .89, (f) -> masterForce.friction(f))

    forces = []

    masterForce = {
      gravity: (g) -> _.each(forces, (force) -> force.gravity(g)); this
      alpha: (a) -> _.each(forces, (force) -> force.alpha(a)); this
      charge: (c) -> _.each(forces, (force) -> force.charge(c)); this
      friction: (f) -> _.each(forces, (force) -> force.friction(f)); this
      resume: () ->  _.each(forces, (force) -> force.resume()); this
      start: () ->  _.each(forces, (force) -> force.start()); this
      apply: (func) ->  _.each(forces, (force) -> func(force)); this
{'fraction_non_alphanumeric': 0.2111736729896682, 'fraction_numerical': 0.00841852074564041, 'mean_word_length': 4.3790061746545135, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5268627', 'n_tokens_mistral': 5699, 'n_tokens_neox': 5483, 'n_words': 1142}