<commit_before>angular.module('gamEvolve.util.dndHelper', [])

.factory "dndHelper", (currentGame, chips) ->
  # On Chrome, we have to use local storage instead of the HTML5 drag and drop API because of security restrictions.
  # We set a special MIME type "application/redwire" in dataTransfer and store the actual data in local storage 
  getDraggedData: (event) ->
    if "application/redwire" not in event.dataTransfer.types then return null
    json = localStorage.getItem("dnd")
    return json && JSON.parse(json) || null

  setDraggedData: (event, data) ->
    json = JSON.stringify(data)
    localStorage.setItem("dnd", json)
    event.dataTransfer.setData('application/redwire', "dnd")

  dragIsFromSameWindow: (dragData) -> dragData.windowId is currentGame.windowId

  getGameCodeForCopy: (gameId, versionId) ->
    # Get source game from localStorage
    # TOOD: verify versionId
    sourceGameJson = localStorage.getItem(gameId)
    if not sourceGameJson then throw new Error("Cannot find game from local storage")
    return JSON.parse(sourceGameJson).data

  # Returns true if the copy is successful, else false
  # Does not update local version
  copySingleChip: (sourceGameCode, targetGameCode, chipType, chipName) ->
    sourceChipCollection = chips.getChipCollection(sourceGameCode, chipType)
    targetChipCollection = chips.getChipCollection(targetGameCode, chipType)

    # Don't bother copying if the things are identical
    if _.isEqual(sourceChipCollection[chipName], targetChipCollection[chipName]) then return false

    # Find new name
    newChipName = if @isChipNameTaken(chipType, chipName) then @findNewChipName(chipType, chipName) else chipName

    # Copy over chip
    targetChipCollection[newChipName] = sourceChipCollection[chipName]
    return true

  # Returns number of chips copied
  # Does not update local version
  copyChip: (gameId, versionId, chip) ->
    # Get source game from localStorage
    sourceGameCode = @getGameCodeForCopy(gameId, versionId)

    # Get chip data
    [chipType, chipName] = chips.getChipTypeAndName(chip)

    chipsToCopy = @listChipsToCopy(sourceGameCode, chip)
    copiedChipCount = 0
    for chipToCopy in chipsToCopy
      if @copySingleChip(sourceGameCode, currentGame.version, chipToCopy...) then copiedChipCount++

    return copiedChipCount

  isChipNameTaken: (chipType, chipName) ->
    chipCollection = chips.getChipCollection(currentGame.version, chipType)
    return chipName of chipCollection

  findNewChipName: (chipType, chipName) ->
    chipCollection = chips.getChipCollection(currentGame.version, chipType)
    return @findNewName(_.keys(chipCollection), chipName)

  findNewName: (existingNames, currentName) ->
    nextName = currentName
    nextIndex = 2
    while nextName in existingNames
      nextName = "#{currentName} #{nextIndex}"
      nextIndex++
    return nextName

  # Return list of dependencies like [[chipAType, chipAName], [chipBType, chipBName], ... ]
  listChipsToCopy: (sourceGameCode, chip) ->
    listChipTree = (chip, list = []) =>
      list.push(chip)
      if chip.children
        for child in chip.children
          listChipTree(child, list)
      return list

    recursiveSearch = (chip, dependencies) =>
      [chipType, chipName] = chips.getChipTypeAndName(chip)

      # Add self to list
      if chipType not in ["emitter", "splitter"]
        dependencies.push([chipType, chipName])

      # Add references to chips in the board
      if chipType is "circuit"
        circuitDependencies = listChipTree(sourceGameCode.circuits[chipName].board)
        for circuitDependency in circuitDependencies
          recursiveSearch(circuitDependency, dependencies)

      # Add references for transformers referenced in the code
      transformerReferences = []
      switch chipType
        when "processor"
          @getTransformerReferences(sourceGameCode.processors[chipName].update, transformerReferences)
        when "switch"
          @getTransformerReferences(sourceGameCode.switches[chipName].listActiveChildren, transformerReferences)
          @getTransformerReferences(sourceGameCode.switches[chipName].handleSignals, transformerReferences)
        when "transformer"
          @getTransformerReferences(sourceGameCode.transformers[chipName].body, transformerReferences)

      # Add references for transformers referenced in pins
      switch chipType
        when "emitter"
          for pinName, pinExpression of chip.emitter
            @getTransformerReferences(pinExpression, transformerReferences)
        when "processor", "switch"
          for pinName, pinExpression of chip.pins.in
            @getTransformerReferences(pinExpression, transformerReferences)
          for pinName, pinExpression of chip.pins.out
            @getTransformerReferences(pinExpression, transformerReferences)

      for tranformerName in transformerReferences
        recursiveSearch({ transformer: tranformerName }, dependencies)

      return dependencies

    return recursiveSearch(chip, [])

  getTransformerReferences: (code, references = []) ->
    r = /transformers.(\w+)|transfromers\[(\w*)\]/g
    loop
      match = r.exec(code)
      if not match then break
      references.push(match[1])
    return references 
<commit_msg>Skip bad references for drag and drop<commit_after>angular.module('gamEvolve.util.dndHelper', [])

.factory "dndHelper", (currentGame, chips) ->
  # On Chrome, we have to use local storage instead of the HTML5 drag and drop API because of security restrictions.
  # We set a special MIME type "application/redwire" in dataTransfer and store the actual data in local storage 
  getDraggedData: (event) ->
    if "application/redwire" not in event.dataTransfer.types then return null
    json = localStorage.getItem("dnd")
    return json && JSON.parse(json) || null

  setDraggedData: (event, data) ->
    json = JSON.stringify(data)
    localStorage.setItem("dnd", json)
    event.dataTransfer.setData('application/redwire', "dnd")

  dragIsFromSameWindow: (dragData) -> dragData.windowId is currentGame.windowId

  getGameCodeForCopy: (gameId, versionId) ->
    # Get source game from localStorage
    # TOOD: verify versionId
    sourceGameJson = localStorage.getItem(gameId)
    if not sourceGameJson then throw new Error("Cannot find game from local storage")
    return JSON.parse(sourceGameJson).data

  # Returns true if the copy is successful, else false
  # Does not update local version
  copySingleChip: (sourceGameCode, targetGameCode, chipType, chipName) ->
    sourceChipCollection = chips.getChipCollection(sourceGameCode, chipType)
    targetChipCollection = chips.getChipCollection(targetGameCode, chipType)

    # Don't bother copying if the things are identical
    if _.isEqual(sourceChipCollection[chipName], targetChipCollection[chipName]) then return false

    # Find new name
    newChipName = if @isChipNameTaken(chipType, chipName) then @findNewChipName(chipType, chipName) else chipName

    # Copy over chip
    targetChipCollection[newChipName] = sourceChipCollection[chipName]
    return true

  # Returns number of chips copied
  # Does not update local version
  copyChip: (gameId, versionId, chip) ->
    # Get source game from localStorage
    sourceGameCode = @getGameCodeForCopy(gameId, versionId)

    # Get chip data
    [chipType, chipName] = chips.getChipTypeAndName(chip)

    chipsToCopy = @listChipsToCopy(sourceGameCode, chip)
    copiedChipCount = 0
    for chipToCopy in chipsToCopy
      if @copySingleChip(sourceGameCode, currentGame.version, chipToCopy...) then copiedChipCount++

    return copiedChipCount

  isChipNameTaken: (chipType, chipName) ->
    chipCollection = chips.getChipCollection(currentGame.version, chipType)
    return chipName of chipCollection

  findNewChipName: (chipType, chipName) ->
    chipCollection = chips.getChipCollection(currentGame.version, chipType)
    return @findNewName(_.keys(chipCollection), chipName)

  findNewName: (existingNames, currentName) ->
    nextName = currentName
    nextIndex = 2
    while nextName in existingNames
      nextName = "#{currentName} #{nextIndex}"
      nextIndex++
    return nextName

  # Return list of dependencies like [[chipAType, chipAName], [chipBType, chipBName], ... ]
  listChipsToCopy: (sourceGameCode, chip) ->
    listChipTree = (chip, list = []) =>
      list.push(chip)
      if chip.children
        for child in chip.children
          listChipTree(child, list)
      return list

    recursiveSearch = (chip, dependencies) =>
      [chipType, chipName] = chips.getChipTypeAndName(chip)
      # If our item is already in the list, return early
      if _.contains(dependencies, [chipType, chipName]) then return dependencies
      # If our item doesn't exist, skip it
      chipCollection = chips.getChipCollection(sourceGameCode, chipType)
      if chipName not of chipCollection then return dependencies

      # Add self to list
      if chipType not in ["emitter", "splitter"]
        dependencies.push([chipType, chipName])

      # Add references to chips in the board
      if chipType is "circuit"
        circuitDependencies = listChipTree(sourceGameCode.circuits[chipName].board)
        for circuitDependency in circuitDependencies
          recursiveSearch(circuitDependency, dependencies)

      # Add references for transformers referenced in the code
      transformerReferences = []
      switch chipType
        when "processor"
          @getTransformerReferences(sourceGameCode.processors[chipName].update, transformerReferences)
        when "switch"
          @getTransformerReferences(sourceGameCode.switches[chipName].listActiveChildren, transformerReferences)
          @getTransformerReferences(sourceGameCode.switches[chipName].handleSignals, transformerReferences)
        when "transformer"
          @getTransformerReferences(sourceGameCode.transformers[chipName].body, transformerReferences)

      # Add references for transformers referenced in pins
      switch chipType
        when "emitter"
          for pinName, pinExpression of chip.emitter
            @getTransformerReferences(pinExpression, transformerReferences)
        when "processor", "switch"
          for pinName, pinExpression of chip.pins.in
            @getTransformerReferences(pinExpression, transformerReferences)
          for pinName, pinExpression of chip.pins.out
            @getTransformerReferences(pinExpression, transformerReferences)

      for transformerName in transformerReferences
        recursiveSearch({ transformer: transformerName }, dependencies)

      return dependencies

    return recursiveSearch(chip, [])

  getTransformerReferences: (code, references = []) ->
    r = /transformers.(\w+)|transformers\[["'](\w*)["']\]/g
    loop
      match = r.exec(code)
      if not match then break
      references.push(match[1] || match[2])
    return references 

{'fraction_non_alphanumeric': 0.08272885869066202, 'fraction_numerical': 0.0008263703975759802, 'mean_word_length': 3.7919049714034316, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, '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': '7642172', 'n_tokens_mistral': 3050, 'n_tokens_neox': 2857, 'n_words': 820}