<commit_before>import { Element as PolymerElement } from '/node_modules/@polymer/polymer/polymer-element.js'
import ReduxMixin from '../../reduxStore.js'
import { playTimeline, resetTimeline, sendUniverseToUsb, sendUniverseToFivetwelve, setTimelineProgress, setChannels, setAllFixtureProperties, resetUniverseAndFixtures } from '../../actions/index.js'
import { batch, clearBatch, fixtureBatch, clearFixtureBatch, modvData } from '/src/utils/index.js'
import '../timeline-scene/index.js'
import { getTimelineScenes, getFixtures } from '../../selectors/index.js'
import * as Fixtures from '../../utils/dmx-fixtures.js'

import '../luminave-elements/button.js'

/*
 * Handle the elements in a timeline
 */
class TimelineManager extends ReduxMixin(PolymerElement) {
  constructor() {
    super()

    // Max length of a scene
    this.measures = 20

    this.timeoutId = undefined

    document.addEventListener('keypress', e => {
      const { code } = e
      // console.log(`Keypress code: ${code}`)

      // Start playback when active element is the body
      if (code === 'Space' && e.target === document.body) {
        e.preventDefault()
        this.handlePlay()
      }
    })
  }

  static get properties() {
    return {
      bpm: {
        type: Number,
        statePath: 'bpm'
      },
      timelineScenes: {
        type: Array,
        statePath: getTimelineScenes
      },
      isPlaying: {
        type: Boolean,
        statePath: 'timelineManager.playing',
        observer: 'observePlaying'
      },
      playLabel: {
        type: String,
        computed: 'computePlayLabel(isPlaying)'
      },

      allFixtures: {
        type: Array,
        statePath: getFixtures
      },

      timelineFixtures: {
        type: Object,
        computed: 'computeFixtures(allFixtures)'
      },

      modvConnected: {
        type: Boolean,
        statePath: 'modvManager.connected'
      }
    }
  }

  computePlayLabel(isPlaying) {
    return isPlaying ? 'Pause' : 'Play'
  }

  handlePlay() {
    this.dispatch(playTimeline(!this.isPlaying))
  }

  handleReset() {
    this.dispatch(resetTimeline())
    this.dispatch(resetUniverseAndFixtures(0))
  }

  // @TODO: Save the current progress into state
  // this.dispatch(setTimelineProgress(this.progress))
  observePlaying() {
    if (this.isPlaying) {
      console.log('playing')
      this.time = new Date()

      this.loop()
    } else {
      console.log('stopped')

      clearTimeout(this.timeoutId)
    }
  }

  normalizeProgress(progress) {
    return progress.toFixed(2)
  }

  loop() {
    if (this.isPlaying) {
      this.duration = ~~(60 / this.bpm * 1000 * this.measures)

      // const {time, duration, paused} = this.state
      const now = new Date()
      const loopEnd = now - this.time > this.duration

      const timeCounter = (now - this.time) / this.duration

      if (loopEnd) {
        this.time = now
      }

      this.progress = this.normalizeProgress(timeCounter * this.measures)

      for (const fixtureId in fixtureBatch) {
        const interpolatedProperties = fixtureBatch[fixtureId].properties
        const fixture = this.timelineFixtures[fixtureId]

          for (const propertyName in interpolatedProperties) {
            // @TODO: only set properties that the fixture understands
            fixture[propertyName] = interpolatedProperties[propertyName]
          }

          // Overwrite the color of every fixture when a connection to modV was established
          if (this.modvConnected && fixture.hasOwnProperty('color')) {

            // Set a specific color from modV
            if (fixture.hasOwnProperty('modvColor')) {

              // @TODO: Fix precision error
              fixture.modvColor = Math.round(fixture.modvColor)

              // Set the color
              fixture.color = modvData.colors.slice((fixture.modvColor - 1) * 3, ((fixture.modvColor - 1) * 3) + 3)

            // Use average color from modV
            } else {
              fixture.color = modvData.average
            }
          }
      }

      // Update the channels of universe 0 with the batch of values collected for the fixtures
      this.dispatch(setChannels(0, [...batch]))

      // Reset the batch so that if a scene is done the values for the attachted fixtures are also reset
      clearBatch()

      // Send the universe to the UsbDmxManager
      window.dispatchEvent(new CustomEvent('send-universe-to-usb-dmx-controller', { detail: { now } }))

      // Send the universe to the FivetwelveManager
      window.dispatchEvent(new CustomEvent('send-universe-to-fivetwelve', { detail: { now } }))

      this.timeoutId = setTimeout(() => {
        // Get the next frame
        requestAnimationFrame(this.loop.bind(this))
      }, 1000 / 30)
<commit_msg>refactor(timeline-manager): modV intergration has to be improved<commit_after>import { Element as PolymerElement } from '/node_modules/@polymer/polymer/polymer-element.js'
import ReduxMixin from '../../reduxStore.js'
import { playTimeline, resetTimeline, sendUniverseToUsb, sendUniverseToFivetwelve, setTimelineProgress, setChannels, setAllFixtureProperties, resetUniverseAndFixtures } from '../../actions/index.js'
import { batch, clearBatch, fixtureBatch, clearFixtureBatch, modvData } from '/src/utils/index.js'
import '../timeline-scene/index.js'
import { getTimelineScenes, getFixtures } from '../../selectors/index.js'
import * as Fixtures from '../../utils/dmx-fixtures.js'

import '../luminave-elements/button.js'

/*
 * Handle the elements in a timeline
 */
class TimelineManager extends ReduxMixin(PolymerElement) {
  constructor() {
    super()

    // Max length of a scene
    this.measures = 20

    this.timeoutId = undefined

    document.addEventListener('keypress', e => {
      const { code } = e
      // console.log(`Keypress code: ${code}`)

      // Start playback when active element is the body
      if (code === 'Space' && e.target === document.body) {
        e.preventDefault()
        this.handlePlay()
      }
    })
  }

  static get properties() {
    return {
      bpm: {
        type: Number,
        statePath: 'bpm'
      },
      timelineScenes: {
        type: Array,
        statePath: getTimelineScenes
      },
      isPlaying: {
        type: Boolean,
        statePath: 'timelineManager.playing',
        observer: 'observePlaying'
      },
      playLabel: {
        type: String,
        computed: 'computePlayLabel(isPlaying)'
      },

      allFixtures: {
        type: Array,
        statePath: getFixtures
      },

      timelineFixtures: {
        type: Object,
        computed: 'computeFixtures(allFixtures)'
      },

      modvConnected: {
        type: Boolean,
        statePath: 'modvManager.connected'
      }
    }
  }

  computePlayLabel(isPlaying) {
    return isPlaying ? 'Pause' : 'Play'
  }

  handlePlay() {
    this.dispatch(playTimeline(!this.isPlaying))
  }

  handleReset() {
    this.dispatch(resetTimeline())
    this.dispatch(resetUniverseAndFixtures(0))
  }

  // @TODO: Save the current progress into state
  // this.dispatch(setTimelineProgress(this.progress))
  observePlaying() {
    if (this.isPlaying) {
      console.log('playing')
      this.time = new Date()

      this.loop()
    } else {
      console.log('stopped')

      clearTimeout(this.timeoutId)
    }
  }

  normalizeProgress(progress) {
    return progress.toFixed(2)
  }

  loop() {
    if (this.isPlaying) {
      this.duration = ~~(60 / this.bpm * 1000 * this.measures)

      // const {time, duration, paused} = this.state
      const now = new Date()
      const loopEnd = now - this.time > this.duration

      const timeCounter = (now - this.time) / this.duration

      if (loopEnd) {
        this.time = now
      }

      this.progress = this.normalizeProgress(timeCounter * this.measures)

      for (const fixtureId in fixtureBatch) {
        const interpolatedProperties = fixtureBatch[fixtureId].properties
        const fixture = this.timelineFixtures[fixtureId]

          for (const propertyName in interpolatedProperties) {
            // @TODO: only set properties that the fixture understands
            fixture[propertyName] = interpolatedProperties[propertyName]
          }

          // Overwrite the color of every fixture when a connection to modV was established
          if (this.modvConnected && fixture.hasOwnProperty('color')) {

            // @TODO: When modvConnected, but no color value yet, we still set the color

            // Set a specific color from modV
            if (fixture.hasOwnProperty('modvColor')) {

              // @TODO: Fix precision error = No interpolation for values that don't change
              fixture.modvColor = Math.round(fixture.modvColor)

              const color = modvData.colors.slice((fixture.modvColor - 1) * 3, ((fixture.modvColor - 1) * 3) + 3)

              // Set the color
              // @TODO: This is still overwriting the color that was previously set on the device
              // which means it's totally useless
              fixture.color = color.length === 3
                ? color
                : fixture.color

            // Use average color from modV
            } else {
              fixture.color = modvData.average
            }
          }
      }

      // Update the channels of universe 0 with the batch of values collected for the fixtures
      this.dispatch(setChannels(0, [...batch]))

      // Reset the batch so that if a scene is done the values for the attachted fixtures are also reset
      clearBatch()

      // Send the universe to the UsbDmxManager
      window.dispatchEvent(new CustomEvent('send-universe-to-usb-dmx-controller', { detail: { now } }))

      // Send the universe to the FivetwelveManager
      window.dispatchEvent(new CustomEvent('send-universe-to-fivetwelve', { detail: { now } }))

      this.timeoutId = setTimeout(() => {
        // Get the next frame
        requestAnimationFrame(this.loop.bind(this))
      }, 1000 / 30)

{'fraction_non_alphanumeric': 0.11068893110688931, 'fraction_numerical': 0.0046995300469953, 'mean_word_length': 2.346269655403145, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '2221306', 'n_tokens_mistral': 2962, 'n_tokens_neox': 2831, 'n_words': 721}