<commit_before>import MainView from './view/MainView';
import AudioController from './AudioController';
import {hslToRgb, lerp} from './util';

export default class Controller {
    constructor(renderingContextFactory) {
        this.keyboardWidth = 1.0;
        this.keyWidth = 0.0075;
        this.keySharpWidth = 0.005;
        this.keyHeight = 0.01;
        this.keyLength = 0.2;

        this.soundNameMeshes = [ null, null ];
        this.audio = [];
        this.audio.push(new AudioController(this.keyboardWidth));
        this.audio.push(new AudioController(this.keyboardWidth));
        this.view = new MainView(this, renderingContextFactory);
        this.view.initialize();
        this.initialize();
    }

    initialize() {
        this.room = new THREE.Mesh(
            new THREE.BoxBufferGeometry( 6, 6, 6, 8, 8, 8 ), this.createRoomMaterial()
        );
        this.room.position.y = 3;

        this.room.receiveShadow = true;
        this.view.scene.add( this.room );

        this.highlightColor = new THREE.Color(0xFFFF00);

        for (let index = 0; index < this.view.renderingContext.controllers.length; index++) {
            const controller = this.view.renderingContext.controllers[index];
            controller.addEventListener('triggerdown', () => { this.onTriggerDown(index); });
            controller.addEventListener('menudown', () => { this.onMenuDown(index); });
        }
        const loader = new THREE.FontLoader();
        this.waveGeometry = [];
        loader.load('resources/helvetiker_regular.typeface.json', ( font ) => {
            this.font = font;
            console.log('font loaded');
            this.addKeysToScene();
            this.createWaveVisualization(0);
            this.createWaveVisualization(1);
        });

    }

    createRoomMaterial() {
        //this.createAudioTexture();

        this.texturedMaterial = new THREE.MeshStandardMaterial( { emissive: 0xfffdfb, emissiveIntensity: 0.15, side: THREE.BackSide } )
        const floorMaterial = new THREE.MeshStandardMaterial( { color: 0xA0A0A0, side: THREE.BackSide } );

        const materials = [];
        for (let i = 0; i < 6; i++) {
            if (i === 3) {
                materials.push(floorMaterial);
            } else {
                materials.push(this.texturedMaterial);
            }
        }

        return new THREE.MeshFaceMaterial(materials);
    }

    createKeyGeometry(isSharp) {
        return new THREE.BoxGeometry(isSharp ? this.keySharpWidth : this.keyWidth, this.keyHeight, this.keyLength);
    }

    addKeysToScene() {
        this.notes = this.audio[0].getNotesWithPosition();
        this.rootObject = new THREE.Object3D();
        const baseMesh = new THREE.Mesh(new THREE.BoxGeometry(1.05*this.keyboardWidth, 1.05*this.keyHeight, 1.2*this.keyLength),
                                        new THREE.MeshStandardMaterial( { color: 0x838380 }));

        baseMesh.position.y -= 1.05*this.keyHeight / 2;
        baseMesh.castShadow = true;
        baseMesh.receiveShadow = true;
        this.rootObject.add(baseMesh);
        // console.log(this.notes);
        for (const n in this.notes) {
            const isSharp = n.includes('#');
            const pos = this.notes[n].position;
            const color = isSharp ? 0x353535 : 0xfffff0;
            const noteMesh = new THREE.Mesh(
                this.createKeyGeometry(isSharp),
                new THREE.MeshStandardMaterial( { color: color, wireframe: false } )
            );
            noteMesh.position.copy(pos);
            //noteMesh.rotation.y = this.audio[0].orientation;
            this.rootObject.add( noteMesh );
            this.notes[n].mesh = noteMesh;
            this.notes[n].isSharp = isSharp;
            this.notes[n].origColor = new THREE.Color(color);

            if (!isSharp) {
                const fontGeometry = new THREE.TextGeometry(n[0], {size: 0.015, height: 0.005, font: this.font});
                const fontMesh = new THREE.Mesh(fontGeometry, new THREE.MeshStandardMaterial({color: 0x3661a5}));
                fontMesh.position.copy(pos);
                fontMesh.position.z -= this.keyLength / 2;
                fontMesh.position.x -= 0.006;
                fontMesh.position.y += this.keyHeight;

                fontMesh.rotation.x -= Math.PI / 6;
                this.rootObject.add(fontMesh);
            }
        }
        this.updateSoundName(0);
        this.updateSoundName(1);
        this.rootObject.position.set(0.4, 0.5, -2);
        // this.rootObject.rotation.set(0, 0, 0);

        this.view.renderingContext.addSpotlight(this.rootObject);
        this.view.scene.add(this.rootObject);
    }

    moveKeys(pos, orientation) {
        const downVec = new THREE.Vector3(0, -0.05, 0);
        downVec.applyEuler(orientation);
        this.rootObject.position.copy(pos);
        this.rootObject.position.add(downVec);
        this.rootObject.rotation.copy(orientation);
    }

    resetHighlights() {
        for (const n in this.notes) {
            const note = this.notes[n];
            note.mesh.material.color = note.origColor;
        }
    }

    createWaveVisualization(index) {
        const geo = new THREE.Geometry();
        const width =  0.5;
        const bufferLength = 1024;
        const offset = (index === 0) ? -this.keyboardWidth/3 : this.keyboardWidth/4.5;
        for (let i = 0; i < bufferLength; i++) {
            const vertex = new THREE.Vector3(offset + -width/2 + i*width/(bufferLength-1), 0.3, -this.keyLength / 2);
            geo.vertices.push(vertex);
        }
        const points = new THREE.Line(geo);

        this.rootObject.add(points);
        this.waveGeometry.push(points);
    }

    updateWaveVisualization(index) {
        if (!this.waveGeometry || index >= this.waveGeometry.length) {
            return;
        }
        const waveform = this.audio[index].getWaveFormData();
        let maxv = 0;
        const halfHeight = 0.2;
        // console.log(waveform.data.length);
        for (let i = 0; i < waveform.length; i++) {
            this.waveGeometry[index].geometry.vertices[i].y = 0.3 + halfHeight*waveform[i];
            maxv = Math.max(maxv, waveform[i]);
        }
        // console.log(maxv);
        this.waveGeometry[index].geometry.verticesNeedUpdate = true;
    }

    createAudioTexture() {
        const size = 64;
        const rgba = new Uint8Array(size * size * 4);
        for (var i = 0; i < size * size; i++) {
            // RGB from 0 to 255
            rgba[4 * i] = 0;
            rgba[4 * i + 1] = 0;
            rgba[4 * i + 2] = 0;
            // OPACITY
            rgba[4 * i + 3] = 255;
        }

        this.audioDataTex = new THREE.DataTexture(rgba, size, size, THREE.RGBAFormat);
        this.audioDataTex.needsUpdate = true;
        this.currentAudioIntensity = 0;
    }

    mapFrequenciesToColor(audio) {
        const freqs = audio.getFrequencyData();
        const stepSize = audio.getFrequencyStep();

        const MAX_FREQ = 2500; //44100/2;
        // 100 hz to 2100 hz
        let freq = 0;
        let colors = [];
        for (let i = 0; i < freqs.length; i++) {
            freq = i*stepSize;
            const amp = freqs[i];
            if (amp > 32) {
                console.log(freq);
                const color = hslToRgb(0.65 + freq/MAX_FREQ*0.35, 0.7 + Math.random()*0.3, 0.5);
                colors.push(color);
            }
        }

        return colors;
    }

    updateAudioTexture() {
        if (!this.audioDataTex) return;

        const colors1 = this.mapFrequenciesToColor(this.audio[0]);
        const colors2 = this.mapFrequenciesToColor(this.audio[1]);
        const colors = colors1.concat(colors2);

        const size = 64;
        const rgba = this.audioDataTex.image.data;
        for (let i = 0; i < size * size; i++) {
            let color = [0, 0, 0];

            if (colors.length > 0) {
                const randIndex = Math.floor((colors.length - 1) * Math.random());
                color = colors[randIndex];
            }
            // RGB from 0 to 255
            rgba[4 * i] = lerp(rgba[4 * i], color[0], 0.05);
            rgba[4 * i + 1] = lerp(rgba[4 * i + 1], color[1], 0.05);
            rgba[4 * i + 2] = lerp(rgba[4 * i + 2], color[2], 0.05);
            // OPACITY
            // rgba[4 * i + 3] = 255;
        }
        // Get average volume

        const volume = Math.max(this.audio[0].getVolume(), this.audio[1].getVolume());
        this.currentAudioIntensity = lerp(this.currentAudioIntensity, volume, 0.05); //this.currentAudioIntensity + 0.05*(volume - this.currentAudioIntensity);
        this.view.renderingContext.hemiLight.intensity = Math.max(0.15, 3*this.currentAudioIntensity);
        this.audioDataTex.needsUpdate = true;
    }

    changeAudioFromController(vrController, audio) {
        if (!this.rootObject) {
            return;
        }

        const pos = vrController.realPosition;

        let gain = 0.99;
        const gamepad = vrController.getGamepad();
        if (gamepad) {
            gain = 0;
            let detuneCents = 0;
            const markerOnPad = vrController.markerOnPad;
            if (gamepad.buttons[0].touched) {
                // gain = Math.log10(1 + 9 * (gamepad.axes[1] + 1) / 2);
                // Let's try the opposite of log, x^4
                const gainNormalized = (Math.max(-0.5, gamepad.axes[1]) + 0.5) / 1.5;
                gain = gainNormalized * gainNormalized * gainNormalized;
                // console.log(gain);
                // detuneCents = 100*gamepad.axes[0];

                const newPosition = new THREE.Vector3(0.0, 0.003785, 0.049204); // Center position
                newPosition.x = -0.020221 + (0.020221 + 0.020221) * (0.5 * gamepad.axes[0] + 0.5);
                newPosition.y = 0.002646 + (0.007248 - 0.002646) * (0.5 * gamepad.axes[1] + 0.5);
                newPosition.z = 0.069432 + (0.029242 - 0.069432) * (0.5 * gamepad.axes[1] + 0.5);

                markerOnPad.position.copy(newPosition);
                markerOnPad.visible = true;
            } else {
                markerOnPad.visible = false;
            }
            audio.detune(detuneCents);
        }

        const posLocal = pos.clone();
        this.rootObject.worldToLocal(posLocal);
        // check is inside space if not, gain 0
        if (Math.abs(posLocal.z) > this.keyLength/2 || Math.abs(posLocal.y) > 0.3 || Math.abs(posLocal.x) > this.keyboardWidth/2) {
            audio.onChange(0, 0);
            return;
        }

        let currentNote = null;
        for (const n in this.notes) {
            const note = this.notes[n];

            if (Math.abs(posLocal.x - note.position.x) < 0.0065) {
                note.mesh.material.color = this.highlightColor;

                if (gamepad && vrController.lastNote !== note) {
                    if (gamepad.haptics) { // Old version. Deprecated
                        gamepad.haptics[0].vibrate(0.25, 25);
                    } else if (gamepad.hapticActuators) {
                        gamepad.hapticActuators[0].pulse(0.25, 25);
                    }
                }
                currentNote = note;
                break;
            }
        }
        if (currentNote) {
            audio.onChange(currentNote.position.x, gain);
        }
        else {
            audio.onChange(posLocal.x, gain);
        }

        vrController.lastNote = currentNote;
    }

    updateSoundName(index) {
        if (!this.font) return;

        if (this.soundNameMeshes[index]) {
            this.rootObject.remove(this.soundNameMeshes[index]);
        }

        const fontSoundGeometry = new THREE.TextGeometry(this.audio[index].getSoundName(), {size: 0.03, height: 0.005, font: this.font});
        const fontDelayGeometry = new THREE.TextGeometry(this.audio[index].isDelayEnabled ? 'delay on' : '', {size: 0.02, height: 0.005, font: this.font});

        this.soundNameMeshes[index] = new THREE.Mesh(fontSoundGeometry, new THREE.MeshStandardMaterial({color: 0xb642f4}));
        this.soundNameMeshes[index].position.z = -this.keyLength / 2;
        this.soundNameMeshes[index].position.x = (index === 0) ? -this.keyboardWidth/3 : this.keyboardWidth/4.5;
        this.soundNameMeshes[index].position.y = 7*this.keyHeight;
        this.soundNameMeshes[index].rotation.x -= Math.PI / 6;

        const delayMesh = new THREE.Mesh(fontDelayGeometry, new THREE.MeshStandardMaterial({color: 0xb642f4}));
        delayMesh.position.y = -2.5*this.keyHeight;
        this.soundNameMeshes[index].add(delayMesh);

        this.rootObject.add(this.soundNameMeshes[index] );
    }

    onTriggerDown(index) {
        this.audio[index].selectNextSound();
        this.updateSoundName(index);
    }

    onMenuDown(index) {
        this.audio[index].toggleDelay();
        this.updateSoundName(index);
    }

    onControllerMoved(controllers, head) {
        this.resetHighlights();
        for (let i = 0; i < controllers.length; i++) {
            if (controllers[i].getButtonState('grips')) {
                this.moveKeys(controllers[i].realPosition, controllers[i].realRotation);
            }

            this.changeAudioFromController(controllers[i], this.audio[i]);
            this.updateWaveVisualization(i);
        }
        // this.updateAudioTexture();
    }
}<commit_msg>Make sharp keys almost as wide as regular keys<commit_after>import MainView from './view/MainView';
import AudioController from './AudioController';
import {hslToRgb, lerp} from './util';

export default class Controller {
    constructor(renderingContextFactory) {
        this.keyboardWidth = 1.0;
        this.keyWidth = 0.0075;
        this.keySharpWidth = 0.0070;
        this.keyHeight = 0.01;
        this.keyLength = 0.2;

        this.soundNameMeshes = [ null, null ];
        this.audio = [];
        this.audio.push(new AudioController(this.keyboardWidth));
        this.audio.push(new AudioController(this.keyboardWidth));
        this.view = new MainView(this, renderingContextFactory);
        this.view.initialize();
        this.initialize();
    }

    initialize() {
        this.room = new THREE.Mesh(
            new THREE.BoxBufferGeometry( 6, 6, 6, 8, 8, 8 ), this.createRoomMaterial()
        );
        this.room.position.y = 3;

        this.room.receiveShadow = true;
        this.view.scene.add( this.room );

        this.highlightColor = new THREE.Color(0xFFFF00);

        for (let index = 0; index < this.view.renderingContext.controllers.length; index++) {
            const controller = this.view.renderingContext.controllers[index];
            controller.addEventListener('triggerdown', () => { this.onTriggerDown(index); });
            controller.addEventListener('menudown', () => { this.onMenuDown(index); });
        }
        const loader = new THREE.FontLoader();
        this.waveGeometry = [];
        loader.load('resources/helvetiker_regular.typeface.json', ( font ) => {
            this.font = font;
            console.log('font loaded');
            this.addKeysToScene();
            this.createWaveVisualization(0);
            this.createWaveVisualization(1);
        });

    }

    createRoomMaterial() {
        //this.createAudioTexture();

        this.texturedMaterial = new THREE.MeshStandardMaterial( { emissive: 0xfffdfb, emissiveIntensity: 0.15, side: THREE.BackSide } )
        const floorMaterial = new THREE.MeshStandardMaterial( { color: 0xA0A0A0, side: THREE.BackSide } );

        const materials = [];
        for (let i = 0; i < 6; i++) {
            if (i === 3) {
                materials.push(floorMaterial);
            } else {
                materials.push(this.texturedMaterial);
            }
        }

        return new THREE.MeshFaceMaterial(materials);
    }

    createKeyGeometry(isSharp) {
        return new THREE.BoxGeometry(isSharp ? this.keySharpWidth : this.keyWidth, this.keyHeight, this.keyLength);
    }

    addKeysToScene() {
        this.notes = this.audio[0].getNotesWithPosition();
        this.rootObject = new THREE.Object3D();
        const baseMesh = new THREE.Mesh(new THREE.BoxGeometry(1.05*this.keyboardWidth, 1.05*this.keyHeight, 1.2*this.keyLength),
                                        new THREE.MeshStandardMaterial( { color: 0x838380 }));

        baseMesh.position.y -= 1.05*this.keyHeight / 2;
        baseMesh.castShadow = true;
        baseMesh.receiveShadow = true;
        this.rootObject.add(baseMesh);
        // console.log(this.notes);
        for (const n in this.notes) {
            const isSharp = n.includes('#');
            const pos = this.notes[n].position;
            const color = isSharp ? 0x353535 : 0xfffff0;
            const noteMesh = new THREE.Mesh(
                this.createKeyGeometry(isSharp),
                new THREE.MeshStandardMaterial( { color: color, wireframe: false } )
            );
            noteMesh.position.copy(pos);
            //noteMesh.rotation.y = this.audio[0].orientation;
            this.rootObject.add( noteMesh );
            this.notes[n].mesh = noteMesh;
            this.notes[n].isSharp = isSharp;
            this.notes[n].origColor = new THREE.Color(color);

            if (!isSharp) {
                const fontGeometry = new THREE.TextGeometry(n[0], {size: 0.015, height: 0.005, font: this.font});
                const fontMesh = new THREE.Mesh(fontGeometry, new THREE.MeshStandardMaterial({color: 0x3661a5}));
                fontMesh.position.copy(pos);
                fontMesh.position.z -= this.keyLength / 2;
                fontMesh.position.x -= 0.006;
                fontMesh.position.y += this.keyHeight;

                fontMesh.rotation.x -= Math.PI / 6;
                this.rootObject.add(fontMesh);
            }
        }
        this.updateSoundName(0);
        this.updateSoundName(1);
        this.rootObject.position.set(0.4, 0.5, -2);
        // this.rootObject.rotation.set(0, 0, 0);

        this.view.renderingContext.addSpotlight(this.rootObject);
        this.view.scene.add(this.rootObject);
    }

    moveKeys(pos, orientation) {
        const downVec = new THREE.Vector3(0, -0.05, 0);
        downVec.applyEuler(orientation);
        this.rootObject.position.copy(pos);
        this.rootObject.position.add(downVec);
        this.rootObject.rotation.copy(orientation);
    }

    resetHighlights() {
        for (const n in this.notes) {
            const note = this.notes[n];
            note.mesh.material.color = note.origColor;
        }
    }

    createWaveVisualization(index) {
        const geo = new THREE.Geometry();
        const width =  0.5;
        const bufferLength = 1024;
        const offset = (index === 0) ? -this.keyboardWidth/3 : this.keyboardWidth/4.5;
        for (let i = 0; i < bufferLength; i++) {
            const vertex = new THREE.Vector3(offset + -width/2 + i*width/(bufferLength-1), 0.3, -this.keyLength / 2);
            geo.vertices.push(vertex);
        }
        const points = new THREE.Line(geo);

        this.rootObject.add(points);
        this.waveGeometry.push(points);
    }

    updateWaveVisualization(index) {
        if (!this.waveGeometry || index >= this.waveGeometry.length) {
            return;
        }
        const waveform = this.audio[index].getWaveFormData();
        let maxv = 0;
        const halfHeight = 0.2;
        // console.log(waveform.data.length);
        for (let i = 0; i < waveform.length; i++) {
            this.waveGeometry[index].geometry.vertices[i].y = 0.3 + halfHeight*waveform[i];
            maxv = Math.max(maxv, waveform[i]);
        }
        // console.log(maxv);
        this.waveGeometry[index].geometry.verticesNeedUpdate = true;
    }

    createAudioTexture() {
        const size = 64;
        const rgba = new Uint8Array(size * size * 4);
        for (var i = 0; i < size * size; i++) {
            // RGB from 0 to 255
            rgba[4 * i] = 0;
            rgba[4 * i + 1] = 0;
            rgba[4 * i + 2] = 0;
            // OPACITY
            rgba[4 * i + 3] = 255;
        }

        this.audioDataTex = new THREE.DataTexture(rgba, size, size, THREE.RGBAFormat);
        this.audioDataTex.needsUpdate = true;
        this.currentAudioIntensity = 0;
    }

    mapFrequenciesToColor(audio) {
        const freqs = audio.getFrequencyData();
        const stepSize = audio.getFrequencyStep();

        const MAX_FREQ = 2500; //44100/2;
        // 100 hz to 2100 hz
        let freq = 0;
        let colors = [];
        for (let i = 0; i < freqs.length; i++) {
            freq = i*stepSize;
            const amp = freqs[i];
            if (amp > 32) {
                console.log(freq);
                const color = hslToRgb(0.65 + freq/MAX_FREQ*0.35, 0.7 + Math.random()*0.3, 0.5);
                colors.push(color);
            }
        }

        return colors;
    }

    updateAudioTexture() {
        if (!this.audioDataTex) return;

        const colors1 = this.mapFrequenciesToColor(this.audio[0]);
        const colors2 = this.mapFrequenciesToColor(this.audio[1]);
        const colors = colors1.concat(colors2);

        const size = 64;
        const rgba = this.audioDataTex.image.data;
        for (let i = 0; i < size * size; i++) {
            let color = [0, 0, 0];

            if (colors.length > 0) {
                const randIndex = Math.floor((colors.length - 1) * Math.random());
                color = colors[randIndex];
            }
            // RGB from 0 to 255
            rgba[4 * i] = lerp(rgba[4 * i], color[0], 0.05);
            rgba[4 * i + 1] = lerp(rgba[4 * i + 1], color[1], 0.05);
            rgba[4 * i + 2] = lerp(rgba[4 * i + 2], color[2], 0.05);
            // OPACITY
            // rgba[4 * i + 3] = 255;
        }
        // Get average volume

        const volume = Math.max(this.audio[0].getVolume(), this.audio[1].getVolume());
        this.currentAudioIntensity = lerp(this.currentAudioIntensity, volume, 0.05); //this.currentAudioIntensity + 0.05*(volume - this.currentAudioIntensity);
        this.view.renderingContext.hemiLight.intensity = Math.max(0.15, 3*this.currentAudioIntensity);
        this.audioDataTex.needsUpdate = true;
    }

    changeAudioFromController(vrController, audio) {
        if (!this.rootObject) {
            return;
        }

        const pos = vrController.realPosition;

        let gain = 0.99;
        const gamepad = vrController.getGamepad();
        if (gamepad) {
            gain = 0;
            let detuneCents = 0;
            const markerOnPad = vrController.markerOnPad;
            if (gamepad.buttons[0].touched) {
                // gain = Math.log10(1 + 9 * (gamepad.axes[1] + 1) / 2);
                // Let's try the opposite of log, x^4
                const gainNormalized = (Math.max(-0.5, gamepad.axes[1]) + 0.5) / 1.5;
                gain = gainNormalized * gainNormalized * gainNormalized;
                // console.log(gain);
                // detuneCents = 100*gamepad.axes[0];

                const newPosition = new THREE.Vector3(0.0, 0.003785, 0.049204); // Center position
                newPosition.x = -0.020221 + (0.020221 + 0.020221) * (0.5 * gamepad.axes[0] + 0.5);
                newPosition.y = 0.002646 + (0.007248 - 0.002646) * (0.5 * gamepad.axes[1] + 0.5);
                newPosition.z = 0.069432 + (0.029242 - 0.069432) * (0.5 * gamepad.axes[1] + 0.5);

                markerOnPad.position.copy(newPosition);
                markerOnPad.visible = true;
            } else {
                markerOnPad.visible = false;
            }
            audio.detune(detuneCents);
        }

        const posLocal = pos.clone();
        this.rootObject.worldToLocal(posLocal);
        // check is inside space if not, gain 0
        if (Math.abs(posLocal.z) > this.keyLength/2 || Math.abs(posLocal.y) > 0.3 || Math.abs(posLocal.x) > this.keyboardWidth/2) {
            audio.onChange(0, 0);
            return;
        }

        let currentNote = null;
        for (const n in this.notes) {
            const note = this.notes[n];

            if (Math.abs(posLocal.x - note.position.x) < 0.0065) {
                note.mesh.material.color = this.highlightColor;

                if (gamepad && vrController.lastNote !== note) {
                    if (gamepad.haptics) { // Old version. Deprecated
                        gamepad.haptics[0].vibrate(0.25, 25);
                    } else if (gamepad.hapticActuators) {
                        gamepad.hapticActuators[0].pulse(0.25, 25);
                    }
                }
                currentNote = note;
                break;
            }
        }
        if (currentNote) {
            audio.onChange(currentNote.position.x, gain);
        }
        else {
            audio.onChange(posLocal.x, gain);
        }

        vrController.lastNote = currentNote;
    }

    updateSoundName(index) {
        if (!this.font) return;

        if (this.soundNameMeshes[index]) {
            this.rootObject.remove(this.soundNameMeshes[index]);
        }

        const fontSoundGeometry = new THREE.TextGeometry(this.audio[index].getSoundName(), {size: 0.03, height: 0.005, font: this.font});
        const fontDelayGeometry = new THREE.TextGeometry(this.audio[index].isDelayEnabled ? 'delay on' : '', {size: 0.02, height: 0.005, font: this.font});

        this.soundNameMeshes[index] = new THREE.Mesh(fontSoundGeometry, new THREE.MeshStandardMaterial({color: 0xb642f4}));
        this.soundNameMeshes[index].position.z = -this.keyLength / 2;
        this.soundNameMeshes[index].position.x = (index === 0) ? -this.keyboardWidth/3 : this.keyboardWidth/4.5;
        this.soundNameMeshes[index].position.y = 7*this.keyHeight;
        this.soundNameMeshes[index].rotation.x -= Math.PI / 6;

        const delayMesh = new THREE.Mesh(fontDelayGeometry, new THREE.MeshStandardMaterial({color: 0xb642f4}));
        delayMesh.position.y = -2.5*this.keyHeight;
        this.soundNameMeshes[index].add(delayMesh);

        this.rootObject.add(this.soundNameMeshes[index] );
    }

    onTriggerDown(index) {
        this.audio[index].selectNextSound();
        this.updateSoundName(index);
    }

    onMenuDown(index) {
        this.audio[index].toggleDelay();
        this.updateSoundName(index);
    }

    onControllerMoved(controllers, head) {
        this.resetHighlights();
        for (let i = 0; i < controllers.length; i++) {
            if (controllers[i].getButtonState('grips')) {
                this.moveKeys(controllers[i].realPosition, controllers[i].realRotation);
            }

            this.changeAudioFromController(controllers[i], this.audio[i]);
            this.updateWaveVisualization(i);
        }
        // this.updateAudioTexture();
    }
}<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import {
  toPairs,
  find
} from 'lodash';
import {
  compose,
  getContext,
  withProps
} from 'recompose';
import { local } from 'redux-fractal';
import { createStore, combineReducers } from 'redux';
import { Link, withRouter } from 'react-router';
import bbox from '@turf/bbox';
import mapboxgl from 'mapbox-gl';
import c from 'classnames';

import Dropdown from '../components/dropdown';
import AssetsEditModal from '../components/assets-edit-modal';

import {
  FETCH_ROAD_GEOMETRY,
  FETCH_ROAD_GEOMETRY_SUCCESS,
  FETCH_ROAD_GEOMETRY_ERROR,
  FETCH_ROAD_PROPERTY,
  FETCH_ROAD_PROPERTY_ERROR,
  FETCH_ROAD_PROPERTY_SUCCESS,
  OP_ON_ROAD_PROPERTY,
  OP_ON_ROAD_PROPERTY_SUCCESS,
  OP_ON_ROAD_PROPERTY_ERROR,
  fetchRoadGeometryEpic,
  fetchRoadPropertyEpic,
  deleteRoadEpic,
  editRoadEpic,
  opOnRoadPropertyEpic
} from '../redux/modules/roads';
import {
  setMapPosition
} from '../redux/modules/map';
import {
  ADMIN_MAP
} from '../constants';
import { mbToken, api, environment } from '../config';
import { showConfirm } from '../components/confirmation-prompt';

mapboxgl.accessToken = mbToken;

class AssetsDetail extends React.Component {
  constructor (props) {
    super(props);

    this.onEditDelete = this.onEditDelete.bind(this);
    this.onEditProperties = this.onEditProperties.bind(this);
    this.onModalClose = this.onModalClose.bind(this);

    this.state = {
      layerRendered: false,
      editModalOpen: false
    };
  }

  componentWillMount () {
    const { vpromm, fetchRoadProperty, fetchRoadGeometry } = this.props;
    fetchRoadProperty(vpromm);
    fetchRoadGeometry(vpromm);
  }

  componentDidMount () {
    this.map = new mapboxgl.Map({
      container: 'aa-map',
      center: [106.12774207395364, 16.185396038978936],
      zoom: 4,
      style: 'mapbox://styles/mapbox/light-v9',
      failIfMajorPerformanceCaveat: false
    });

    this.map.addControl(new mapboxgl.ScaleControl({ unit: 'metric' }));
    this.map.addControl(new mapboxgl.NavigationControl());

    this.map.on('load', () => {
      this.setupMapStyle();
    });
  }

  componentWillReceiveProps (nextProps) {
    if (this.props.roadGeo.fetching && !nextProps.roadGeo.fetching && !nextProps.roadGeo.error) {
      this.setupMapStyle();
    }
  }

  // componentWillUnmount () {
  //   const { lng, lat } = this.map.getCenter();
  //   const zoom = this.map.getZoom();
  //   this.props.setMapPosition(lng, lat, zoom);
  // }

  setupMapStyle () {
    const { fetched, data } = this.props.roadGeo;

    if (!fetched || this.map.getSource('road-geometry')) return;

    this.map.addSource('road-geometry', { type: 'geojson', data: data });
    this.map.addLayer({
      id: `road-geometry-layer`,
      type: 'line',
      source: 'road-geometry',
      paint: {
        'line-width': 2,
        'line-color': '#808080'
      }
    });

    if (data.features.length > 0) {
      this.map.fitBounds(bbox(data), { padding: 20 });
    }
  }

  onModalClose (data = {}) {
    this.setState({ editModalOpen: false });
    if (data.action === 'refresh') {
      // Why the setTimeout you ask?
      // For some reason redux-fractal doesn't play well with thunks.
      // It thinks that the action is being dispatched from a reducer and
      // throws an error. "Reducers may not dispatch actions."
      // This is meant to refresh the data after properties are saved.
      setTimeout(() => { this.props.fetchRoadProperty(this.props.vpromm); }, 0);
    } else if (data.action === 'redirect') {
      setTimeout(() => { this.props.router.push({pathname: `/${this.props.language}/assets/roads/${data.vpromm}/`}); }, 0);
    }
  }

  onEditProperties (e) {
    e.preventDefault();
    this.setState({ editModalOpen: true });
  }

  onEditDelete (e) {
    e.preventDefault();
    showConfirm({
      title: 'Delete road',
      body: (

Are you sure you want to delete road {this.props.vpromm}?

This action is irreversible.

      )
    }, () => {
      this.props.deleteRoad(this.props.vpromm);
      this.props.router.push({pathname: `/${this.props.language}/assets`});
    });
  }

  renderProperties () {
    const { fetched, data } = this.props.roadProps;

    if (!fetched) return null;

    let propNames = Object.keys(data.properties);
    propNames.sort((a, b) => a.toLowerCase() > b.toLowerCase() ? 1 : -1);

    const renderDlItem = (name) => {
      return [
        <dt key={`dt-${name}`}>{name}
,
        <dd key={`dd-${name}`}>{data.properties[name] || '-'}

      ];
    };

    return (

Attributes

          {propNames.map(renderDlItem)}

    );
  }

  renderReviewStatus () {
    const reviewState = 'pending';
    const classForState = (state) => c('drop__menu-item', {'drop__menu-item--active': reviewState === state});

    // Temp
    const noop = e => e.preventDefault();

    return (
      <Dropdown
        className='review-status-menu'
        triggerClassName='button button--primary-raised-light'
        triggerActiveClassName='button--active'
        triggerText={reviewState}
        triggerTitle='Change review state'
        direction='down'
        alignment='center' >

Pending

Reviewed

      </Dropdown>
    );
  }

  render () {
    const { vpromm, language } = this.props;

    return (

{vpromm}

          {this.renderReviewStatus()}

          <a href={`${api}/properties/roads/${vpromm}.geojson`} className='button button--base-raised-light'>Download
          <Dropdown
            className='browse-menu'
            triggerClassName='button button--primary-raised-dark'
            triggerActiveClassName='button--active'
            triggerText='Edit'
            triggerTitle='Toggle menu options'
            direction='down'
            alignment='right' >

Attributes

<Link to={`/${language}/editor?way=823`} className='drop__menu-item'>Geometry</Link>

Delete

          </Dropdown>

        {this.renderProperties()}

        {this.props.roadProps.fetched ? <AssetsEditModal
          revealed={this.state.editModalOpen}
          onCloseClick={this.onModalClose}
          opOnRoadProperty={this.props.opOnRoadProperty}
          editRoad={this.props.editRoad}
          vpromm={vpromm}
          roadPropsOp={this.props.roadPropsOp}
          roadProps={this.props.roadProps} /> : null}

    );
  }
}

if (environment !== 'production') {
  AssetsDetail.propTypes = {
    vpromm: PropTypes.string,
    router: PropTypes.object,
    roadGeo: PropTypes.object,
    roadProps: PropTypes.object,
    roadPropsOp: PropTypes.object,
    language: PropTypes.string,
    fetchRoadProperty: PropTypes.func,
    fetchRoadGeometry: PropTypes.func,
    deleteRoad: PropTypes.func,
    opOnRoadProperty: PropTypes.func,
    editRoad: PropTypes.func
  };
}

//
//
//

// Road properties state and reducer.
const stateRoadProps = {
  fetched: false,
  fetching: false,
  data: {}
};

const reducerRoadProps = (state = stateRoadProps, action) => {
  switch (action.type) {
    case FETCH_ROAD_PROPERTY:
      return {...state, fetching: true, fetched: false, error: false};
    case FETCH_ROAD_PROPERTY_ERROR:
      return {...state, fetching: false, fetched: true, error: true};
    case FETCH_ROAD_PROPERTY_SUCCESS:
      return {...state, fetching: false, fetched: true, data: action.properties};
  }

  return state;
};

// Road geometry state and reducer.
const stateRoadGeo = {
  fetched: false,
  fetching: false,
  data: {}
};

const reducerRoadGeo = (state = stateRoadGeo, action) => {
  switch (action.type) {
    case FETCH_ROAD_GEOMETRY:
      return {...state, fetching: true, fetched: false, error: false};
    case FETCH_ROAD_GEOMETRY_ERROR:
      return {...state, fetching: false, fetched: true, error: true};
    case FETCH_ROAD_GEOMETRY_SUCCESS:
      return {...state, fetching: false, fetched: true, data: action.geoJSON};
  }

  return state;
};

// Road operations state and reducer.
// Handles operations done to the properties.
const stateOpOnRoad = {
  processing: false,
  data: {}
};

const reducerOpOnRoad = (state = stateOpOnRoad, action) => {
  switch (action.type) {
    case OP_ON_ROAD_PROPERTY:
      return {...state, processing: true, error: false};
    case OP_ON_ROAD_PROPERTY_SUCCESS:
      return {...state, processing: false, error: false, data: action.data};
    case OP_ON_ROAD_PROPERTY_ERROR:
      return {...state, processing: false, error: true};
  }

  return state;
};

const reducer = combineReducers({
  properties: reducerRoadProps,
  geometry: reducerRoadGeo,
  operations: reducerOpOnRoad
});

// Notes:
// The state for each road is handled locally with redux-fractal.
// The data from the api is also saved in the global state but since each
// mapStateToProps (either local() or connect()) causes a render is difficult
// to merge both therefore we're handling everything here.
export default compose(
  withRouter,
  getContext({ language: React.PropTypes.string }),
  withProps(({ language, params: { vpromm } }) => {
    const [aaId, { name }] = find(
      toPairs(ADMIN_MAP.province),
      ([aaId, { id }]) => id === vpromm.substring(0, 2)
    );

    return {
      vpromm,
      provinceName: name,
      aaId
    };
  }),
  local({
    key: ({ vpromm }) => `${vpromm}-road-map`,
    createStore: () => createStore(reducer),
    mapStateToProps: (state) => ({
      roadProps: state.properties,
      roadGeo: state.geometry,
      roadPropsOp: state.operations
    }),
    filterGlobalActions: ({ type }) => [
      FETCH_ROAD_GEOMETRY,
      FETCH_ROAD_GEOMETRY_SUCCESS,
      FETCH_ROAD_GEOMETRY_ERROR,
      FETCH_ROAD_PROPERTY,
      FETCH_ROAD_PROPERTY_SUCCESS,
      FETCH_ROAD_PROPERTY_ERROR,
      OP_ON_ROAD_PROPERTY,
      OP_ON_ROAD_PROPERTY_SUCCESS,
      OP_ON_ROAD_PROPERTY_ERROR
    ].indexOf(type) > -1
  }),
  connect(
    (state, props) => ({}),
    (dispatch) => ({
      setMapPosition: (...args) => dispatch(setMapPosition(...args)),
      fetchRoadGeometry: (...args) => dispatch(fetchRoadGeometryEpic(...args)),
      fetchRoadProperty: (...args) => dispatch(fetchRoadPropertyEpic(...args)),
      opOnRoadProperty: (...args) => dispatch(opOnRoadPropertyEpic(...args)),
      deleteRoad: (...args) => dispatch(deleteRoadEpic(...args)),
      editRoad: (...args) => dispatch(editRoadEpic(...args))
    })
  )
)(AssetsDetail);

<commit_msg>Fix change of vrpomm on url<commit_after>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import {
  toPairs,
  find
} from 'lodash';
import {
  compose,
  getContext,
  withProps
} from 'recompose';
import { local } from 'redux-fractal';
import { createStore, combineReducers } from 'redux';
import { Link, withRouter } from 'react-router';
import bbox from '@turf/bbox';
import mapboxgl from 'mapbox-gl';
import c from 'classnames';

import Dropdown from '../components/dropdown';
import AssetsEditModal from '../components/assets-edit-modal';

import {
  FETCH_ROAD_GEOMETRY,
  FETCH_ROAD_GEOMETRY_SUCCESS,
  FETCH_ROAD_GEOMETRY_ERROR,
  FETCH_ROAD_PROPERTY,
  FETCH_ROAD_PROPERTY_ERROR,
  FETCH_ROAD_PROPERTY_SUCCESS,
  OP_ON_ROAD_PROPERTY,
  OP_ON_ROAD_PROPERTY_SUCCESS,
  OP_ON_ROAD_PROPERTY_ERROR,
  fetchRoadGeometryEpic,
  fetchRoadPropertyEpic,
  deleteRoadEpic,
  editRoadEpic,
  opOnRoadPropertyEpic
} from '../redux/modules/roads';
import {
  setMapPosition
} from '../redux/modules/map';
import {
  ADMIN_MAP
} from '../constants';
import { mbToken, api, environment } from '../config';
import { showConfirm } from '../components/confirmation-prompt';

mapboxgl.accessToken = mbToken;

class AssetsDetail extends React.Component {
  constructor (props) {
    super(props);

    this.onEditDelete = this.onEditDelete.bind(this);
    this.onEditProperties = this.onEditProperties.bind(this);
    this.onModalClose = this.onModalClose.bind(this);

    this.state = {
      layerRendered: false,
      editModalOpen: false
    };
  }

  componentWillMount () {
    const { vpromm, fetchRoadProperty, fetchRoadGeometry } = this.props;
    fetchRoadProperty(vpromm);
    fetchRoadGeometry(vpromm);
  }

  componentDidMount () {
    this.map = new mapboxgl.Map({
      container: 'aa-map',
      center: [106.12774207395364, 16.185396038978936],
      zoom: 4,
      style: 'mapbox://styles/mapbox/light-v9',
      failIfMajorPerformanceCaveat: false
    });

    this.map.addControl(new mapboxgl.ScaleControl({ unit: 'metric' }));
    this.map.addControl(new mapboxgl.NavigationControl());

    this.map.on('load', () => {
      this.setupMapStyle();
    });
  }

  componentWillReceiveProps (nextProps) {
    if (this.props.vpromm !== nextProps.vpromm) {
      this.props.fetchRoadProperty(nextProps.vpromm);
      this.props.fetchRoadGeometry(nextProps.vpromm);
    }

    if (this.props.roadGeo.fetching && !nextProps.roadGeo.fetching && !nextProps.roadGeo.error) {
      this.setupMapStyle();
    }
  }

  // componentWillUnmount () {
  //   const { lng, lat } = this.map.getCenter();
  //   const zoom = this.map.getZoom();
  //   this.props.setMapPosition(lng, lat, zoom);
  // }

  setupMapStyle () {
    const { fetched, data } = this.props.roadGeo;

    if (!fetched || this.map.getSource('road-geometry')) return;

    this.map.addSource('road-geometry', { type: 'geojson', data: data });
    this.map.addLayer({
      id: `road-geometry-layer`,
      type: 'line',
      source: 'road-geometry',
      paint: {
        'line-width': 2,
        'line-color': '#808080'
      }
    });

    if (data.features.length > 0) {
      this.map.fitBounds(bbox(data), { padding: 20 });
    }
  }

  onModalClose (data = {}) {
    this.setState({ editModalOpen: false });
    if (data.action === 'refresh') {
      // Why the setTimeout you ask?
      // For some reason redux-fractal doesn't play well with thunks.
      // It thinks that the action is being dispatched from a reducer and
      // throws an error. "Reducers may not dispatch actions."
      // This is meant to refresh the data after properties are saved.
      setTimeout(() => { this.props.fetchRoadProperty(this.props.vpromm); }, 0);
    } else if (data.action === 'redirect') {
      setTimeout(() => { this.props.router.push({pathname: `/${this.props.language}/assets/road/${data.vpromm}/`}); }, 0);
    }
  }

  onEditProperties (e) {
    e.preventDefault();
    this.setState({ editModalOpen: true });
  }

  onEditDelete (e) {
    e.preventDefault();
    showConfirm({
      title: 'Delete road',
      body: (

Are you sure you want to delete road {this.props.vpromm}?

This action is irreversible.

      )
    }, () => {
      this.props.deleteRoad(this.props.vpromm);
      this.props.router.push({pathname: `/${this.props.language}/assets`});
    });
  }

  renderProperties () {
    const { fetched, data } = this.props.roadProps;

    if (!fetched) return null;

    let propNames = Object.keys(data.properties);
    propNames.sort((a, b) => a.toLowerCase() > b.toLowerCase() ? 1 : -1);

    const renderDlItem = (name) => {
      return [
        <dt key={`dt-${name}`}>{name}
,
        <dd key={`dd-${name}`}>{data.properties[name] || '-'}

      ];
    };

    return (

Attributes

          {propNames.map(renderDlItem)}

    );
  }

  renderReviewStatus () {
    const reviewState = 'pending';
    const classForState = (state) => c('drop__menu-item', {'drop__menu-item--active': reviewState === state});

    // Temp
    const noop = e => e.preventDefault();

    return (
      <Dropdown
        className='review-status-menu'
        triggerClassName='button button--primary-raised-light'
        triggerActiveClassName='button--active'
        triggerText={reviewState}
        triggerTitle='Change review state'
        direction='down'
        alignment='center' >

Pending

Reviewed

      </Dropdown>
    );
  }

  render () {
    const { vpromm, language } = this.props;

    return (

{vpromm}

          {this.renderReviewStatus()}

          <a href={`${api}/properties/roads/${vpromm}.geojson`} className='button button--base-raised-light'>Download
          <Dropdown
            className='browse-menu'
            triggerClassName='button button--primary-raised-dark'
            triggerActiveClassName='button--active'
            triggerText='Edit'
            triggerTitle='Toggle menu options'
            direction='down'
            alignment='right' >

Attributes

<Link to={`/${language}/editor?way=823`} className='drop__menu-item'>Geometry</Link>

Delete

          </Dropdown>

        {this.renderProperties()}

        {this.props.roadProps.fetched ? <AssetsEditModal
          revealed={this.state.editModalOpen}
          onCloseClick={this.onModalClose}
          opOnRoadProperty={this.props.opOnRoadProperty}
          editRoad={this.props.editRoad}
          vpromm={vpromm}
          roadPropsOp={this.props.roadPropsOp}
          roadProps={this.props.roadProps} /> : null}

    );
  }
}

if (environment !== 'production') {
  AssetsDetail.propTypes = {
    vpromm: PropTypes.string,
    router: PropTypes.object,
    roadGeo: PropTypes.object,
    roadProps: PropTypes.object,
    roadPropsOp: PropTypes.object,
    language: PropTypes.string,
    fetchRoadProperty: PropTypes.func,
    fetchRoadGeometry: PropTypes.func,
    deleteRoad: PropTypes.func,
    opOnRoadProperty: PropTypes.func,
    editRoad: PropTypes.func
  };
}

//
//
//

// Road properties state and reducer.
const stateRoadProps = {
  fetched: false,
  fetching: false,
  data: {}
};

const reducerRoadProps = (state = stateRoadProps, action) => {
  switch (action.type) {
    case FETCH_ROAD_PROPERTY:
      return {...state, fetching: true, fetched: false, error: false};
    case FETCH_ROAD_PROPERTY_ERROR:
      return {...state, fetching: false, fetched: true, error: true};
    case FETCH_ROAD_PROPERTY_SUCCESS:
      return {...state, fetching: false, fetched: true, data: action.properties};
  }

  return state;
};

// Road geometry state and reducer.
const stateRoadGeo = {
  fetched: false,
  fetching: false,
  data: {}
};

const reducerRoadGeo = (state = stateRoadGeo, action) => {
  switch (action.type) {
    case FETCH_ROAD_GEOMETRY:
      return {...state, fetching: true, fetched: false, error: false};
    case FETCH_ROAD_GEOMETRY_ERROR:
      return {...state, fetching: false, fetched: true, error: true};
    case FETCH_ROAD_GEOMETRY_SUCCESS:
      return {...state, fetching: false, fetched: true, data: action.geoJSON};
  }

  return state;
};

// Road operations state and reducer.
// Handles operations done to the properties.
const stateOpOnRoad = {
  processing: false,
  data: {}
};

const reducerOpOnRoad = (state = stateOpOnRoad, action) => {
  switch (action.type) {
    case OP_ON_ROAD_PROPERTY:
      return {...state, processing: true, error: false};
    case OP_ON_ROAD_PROPERTY_SUCCESS:
      return {...state, processing: false, error: false, data: action.data};
    case OP_ON_ROAD_PROPERTY_ERROR:
      return {...state, processing: false, error: true};
  }

  return state;
};

const reducer = combineReducers({
  properties: reducerRoadProps,
  geometry: reducerRoadGeo,
  operations: reducerOpOnRoad
});

// Notes:
// The state for each road is handled locally with redux-fractal.
// The data from the api is also saved in the global state but since each
// mapStateToProps (either local() or connect()) causes a render is difficult
// to merge both therefore we're handling everything here.
export default compose(
  withRouter,
  getContext({ language: React.PropTypes.string }),
  withProps(({ language, params: { vpromm } }) => {
    const [aaId, { name }] = find(
      toPairs(ADMIN_MAP.province),
      ([aaId, { id }]) => id === vpromm.substring(0, 2)
    );

    return {
      vpromm,
      provinceName: name,
      aaId
    };
  }),
  local({
    key: ({ vpromm }) => `${vpromm}-road-map`,
    createStore: () => createStore(reducer),
    mapStateToProps: (state) => ({
      roadProps: state.properties,
      roadGeo: state.geometry,
      roadPropsOp: state.operations
    }),
    filterGlobalActions: ({ type }) => [
      FETCH_ROAD_GEOMETRY,
      FETCH_ROAD_GEOMETRY_SUCCESS,
      FETCH_ROAD_GEOMETRY_ERROR,
      FETCH_ROAD_PROPERTY,
      FETCH_ROAD_PROPERTY_SUCCESS,
      FETCH_ROAD_PROPERTY_ERROR,
      OP_ON_ROAD_PROPERTY,
      OP_ON_ROAD_PROPERTY_SUCCESS,
      OP_ON_ROAD_PROPERTY_ERROR
    ].indexOf(type) > -1
  }),
  connect(
    (state, props) => ({}),
    (dispatch) => ({
      setMapPosition: (...args) => dispatch(setMapPosition(...args)),
      fetchRoadGeometry: (...args) => dispatch(fetchRoadGeometryEpic(...args)),
      fetchRoadProperty: (...args) => dispatch(fetchRoadPropertyEpic(...args)),
      opOnRoadProperty: (...args) => dispatch(opOnRoadPropertyEpic(...args)),
      deleteRoad: (...args) => dispatch(deleteRoadEpic(...args)),
      editRoad: (...args) => dispatch(editRoadEpic(...args))
    })
  )
)(AssetsDetail);

<|endoftext|>


<commit_before>/**
 * Created by bjdmeest on 4/12/2015.
 */
CKEDITOR.dialog.add('fremeEntityDialog', function (editor) {
    var langs = [['Dutch', 'NL'], ['English', 'EN'], ['French ', 'FR'], ['German ', 'DE'], ['Italian ', 'IT'], ['Spanish ', 'ES']];
    var datasetsJSON = [
        {
            "Name": "dbpedia",
            "Description": "DBpedia datasets for all languages",
            "TotalEntities": 14200830,
            "CreationTime": 1435966058019
        },
        {
            "Name": "onld",
            "Description": "Organization Name Linked Data (http://www.lib.ncsu.edu/ld/onld/)",
            "TotalEntities": 5153,
            "CreationTime": 1442404750691
        },
        {
            "Name": "geopolitical",
            "Description": "Geopolitical ontology (http://www.fao.org/countryprofiles/geoinfo/en/)",
            "TotalEntities": 5905,
            "CreationTime": 1442405451333
        },
        {
            "Name": "global_airports",
            "Description": "A dataset of global airports featuring their names and unique IATA/ICAO identifiers.",
            "TotalEntities": 18586,
            "CreationTime": 1442580539219
        },
        {
            "Name": "viaf",
            "Description": "The VIAF® (Virtual International Authority File) dataset is a collection of multiple name authority files. (http://viaf.org/)",
            "TotalEntities": 44119711,
            "CreationTime": 1444922284386
        },
        {
            "Name": "orcid",
            "Description": "The ORCID dataset provides persistent digital identifier for researchers (http://orcid.org/)",
            "TotalEntities": 1321116,
            "CreationTime": 1444922402140
        },
        {
            "Name": "mydataset",
            "Description": "",
            "TotalEntities": 16,
            "CreationTime": 1446198583025
        },
        {
            "Name": "NAME",
            "Description": "",
            "TotalEntities": 0,
            "CreationTime": 1446201950406
        }
    ];
    var datasets = [];
    for (var i = 0; i < datasetsJSON.length; i++) {
        var currSet = datasetsJSON[i];
        if (currSet.Description !== '' && currSet.TotalEntities > 0) {
            datasets.push([currSet.Description, currSet.Name]);
        }
    }

    function link(sourceText, lang, dataset, cb) {
        doRequest('POST',
            'http://api.freme-project.eu/current/e-entity/freme-ner/documents?informat=text%2Fhtml&outformat=text%2Fhtml&language=' + lang.toLowerCase() + '&dataset=' + dataset + '&mode=all',
            '
' + sourceText + '
',
            {'Content-Type': 'text/html', Accept: 'text/n3'},
            function (results) {
                cb(null, results.slice(results.indexOf('
') + 3, results.lastIndexOf('
')));
            },
            function () {
                cb(new Error('Linking error'));
            }
        );

    }

    function doRequest(method, url, data, headers, success, error) {
        $.ajax({
                method: method,
                headers: headers,
                data: data,
                url: url
            })
            .done(success)
            .fail(error);
    }

    function endIt(todo, eEntityNot) {
        if (todo === 0) {
            eEntityNot.update({type: 'success', message: 'e-Entity completed!'});
        }
    }

    return {
        title: 'FREME Entity',
        minWidth: 400,
        minHeight: 200,
        contents: [
            {
                id: 'tab-main',
                label: 'Parameter selection',
                elements: [
                    {
                        type: 'select',
                        id: 'lang',
                        label: 'Language',
                        items: langs,
                        default: 'EN'
                    },
                    {
                        type: 'select',
                        id: 'dataset',
                        label: 'Target Language',
                        items: datasets,
                        default: 'dbpedia'
                    }
                ]
            }
        ],
        onOk: function () {
            var lang = this.getValueOf('tab-main', 'lang'),
                dataset = this.getValueOf('tab-main', 'dataset'),
                doc = editor.document,
                goodTags = ['h1', 'h2', 'h3', 'blockquote', 'p'],
                todo = 0;
            var eEntityNot = editor.showNotification('e-Entity started!');
            for (var i = 0; i < goodTags.length; i++) {
                var nodes = doc.getElementsByTag(goodTags[i]);
                todo += nodes.count();
                for (var j = 0; j < nodes.count(); j++) {
                    var node = nodes.getItem(j);
                    (function (node, lang, dataset) {
                        var $el = $(node.$.outerHTML);
                        $el.find('[its-ta-class-ref]').each(function() {
                            this.outerHTML = $(this).text();
                        });
                        link($el.html(), lang, dataset, function (err, html) {
                            todo--;
                            if (err) {
                                return console.log(err);
                            }
                            node.setHtml(html);
                            endIt(todo, eEntityNot);
                        });
                    })(node, lang, dataset);
                }
            }

        }
    };
});
<commit_msg>no more calls parallelly. Also: progress bar!<commit_after>/**
 * Created by bjdmeest on 4/12/2015.
 */
CKEDITOR.dialog.add('fremeEntityDialog', function (editor) {
    var langs = [['Dutch', 'NL'], ['English', 'EN'], ['French ', 'FR'], ['German ', 'DE'], ['Italian ', 'IT'], ['Spanish ', 'ES']];
    var datasetsJSON = [
        {
            "Name": "dbpedia",
            "Description": "DBpedia datasets for all languages",
            "TotalEntities": 14200830,
            "CreationTime": 1435966058019
        },
        {
            "Name": "onld",
            "Description": "Organization Name Linked Data (http://www.lib.ncsu.edu/ld/onld/)",
            "TotalEntities": 5153,
            "CreationTime": 1442404750691
        },
        {
            "Name": "geopolitical",
            "Description": "Geopolitical ontology (http://www.fao.org/countryprofiles/geoinfo/en/)",
            "TotalEntities": 5905,
            "CreationTime": 1442405451333
        },
        {
            "Name": "global_airports",
            "Description": "A dataset of global airports featuring their names and unique IATA/ICAO identifiers.",
            "TotalEntities": 18586,
            "CreationTime": 1442580539219
        },
        {
            "Name": "viaf",
            "Description": "The VIAF® (Virtual International Authority File) dataset is a collection of multiple name authority files. (http://viaf.org/)",
            "TotalEntities": 44119711,
            "CreationTime": 1444922284386
        },
        {
            "Name": "orcid",
            "Description": "The ORCID dataset provides persistent digital identifier for researchers (http://orcid.org/)",
            "TotalEntities": 1321116,
            "CreationTime": 1444922402140
        },
        {
            "Name": "mydataset",
            "Description": "",
            "TotalEntities": 16,
            "CreationTime": 1446198583025
        },
        {
            "Name": "NAME",
            "Description": "",
            "TotalEntities": 0,
            "CreationTime": 1446201950406
        }
    ];
    var datasets = [];
    for (var i = 0; i < datasetsJSON.length; i++) {
        var currSet = datasetsJSON[i];
        if (currSet.Description !== '' && currSet.TotalEntities > 0) {
            datasets.push([currSet.Description, currSet.Name]);
        }
    }

    function link(sourceText, lang, dataset, cb) {
        doRequest('POST',
            'http://api.freme-project.eu/current/e-entity/freme-ner/documents?informat=text%2Fhtml&outformat=text%2Fhtml&language=' + lang.toLowerCase() + '&dataset=' + dataset + '&mode=all',
            '
' + sourceText + '
',
            {'Content-Type': 'text/html', Accept: 'text/n3'},
            function (results) {
                cb(null, results.slice(results.indexOf('
') + 3, results.lastIndexOf('
')));
            },
            function () {
                cb(new Error('Linking error'));
            }
        );

    }

    function doRequest(method, url, data, headers, success, error) {
        $.ajax({
                method: method,
                headers: headers,
                data: data,
                url: url
            })
            .done(success)
            .fail(error);
    }

    function endIt(todo, eEntityNot) {
        if (todo === 0) {
            eEntityNot.update({type: 'success', message: 'e-Entity completed!'});
        }
    }

    return {
        title: 'FREME Entity',
        minWidth: 400,
        minHeight: 200,
        contents: [
            {
                id: 'tab-main',
                label: 'Parameter selection',
                elements: [
                    {
                        type: 'select',
                        id: 'lang',
                        label: 'Language',
                        items: langs,
                        default: 'EN'
                    },
                    {
                        type: 'select',
                        id: 'dataset',
                        label: 'Target Language',
                        items: datasets,
                        default: 'dbpedia'
                    }
                ]
            }
        ],
        onOk: function () {
            var lang = this.getValueOf('tab-main', 'lang'),
                dataset = this.getValueOf('tab-main', 'dataset'),
                doc = editor.document,
                goodTags = ['h1', 'h2', 'h3', 'blockquote', 'p'],
                todo = 0;
            var eEntityNot = editor.showNotification('e-Entity started!', 'progress', 0);
            var nodes = [];
            for (var i = 0; i < goodTags.length; i++) {
                var nodeList = doc.getElementsByTag(goodTags[i]);
                for (var j = 0; j < nodeList.count(); j++) {
                    nodes.push(nodeList.getItem(j));
                }
            }
            asyncLoop({
                length: nodes.length,
                functionToLoop: function (loop, i) {
                    var node = nodes[i];
                    var $el = $(node.$.outerHTML);
                    $el.find('[its-ta-class-ref]').each(function () {
                        this.outerHTML = $(this).text();
                    });
                    link($el.html(), lang, dataset, function (err, html) {
                        todo--;
                        if (err) {
                            return console.log(err);
                        }
                        node.setHtml(html);
                        eEntityNot.update({progress: (i + 1) / nodes.length});
                        return loop();
                    });
                },
                callback: function () {
                    eEntityNot.update({type: 'success', message: 'e-Entity completed!'});
                }
            });
        }
    };
});

var asyncLoop = function (o) {
    var i = -1;

    var loop = function () {
        i++;
        if (i == o.length) {
            o.callback();
            return;
        }
        o.functionToLoop(loop, i);
    };
    loop();//init
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  name: 'Neo4J',

  startup: function (host, cb) {
    var neo4j = require('seraph')({
      server: 'http://' + host + ':7474',
      user: 'neo4j',
      pass: 'abc'
    });

    cb(neo4j);
  },

  warmup: function (db, cb) {
    module.exports.getCollection(db, 'profiles', function (err, coll) {
      if (err) return cb(err);

      module.exports.aggregate(db, coll, function (err, result) {
        if (err) return cb(err);

        console.log('INFO warmup done');

        return cb(null);
      });
    });
  },

  getCollection: function (db, name, cb) {
    cb(null, name.toUpperCase());
  },

  dropCollection: function (db, name, cb) {
    name = name.toUpperCase();

    db.nodesWithLabel(name, function (err, results) {
      if (err) cb(err);

      console.log('INFO clearing %d documents in %s', results.length, name);

      var i = -1;
      var next = function (err) {
        // if (err) console.log('ERROR %s', err);
        if (err) cb(err);

        ++i;

        if (i === results.length) {
          cb();
        }
        else {
          var obj = {id: results[i].id};
          db.delete(obj, function (err) {
            next(err);
          });
        }
      };

      next();
    });
  },

  createCollection: function (db, name, cb) {
    cb();
  },

  getDocument: function (db, coll, id, cb) {
    var obj = {_key: 'P/' + id};
    db.find(obj, false, coll, cb);
  },

  saveDocument: function (db, coll, doc, cb) {
    db.save(doc, coll, cb);
  },

  aggregate: function (db, coll, cb) {
    db.query('MATCH (f:' + coll + ') WITH f.AGE as AGE RETURN AGE, count(*)',
      function (err, result) {
        if (err) return cb(err);

        cb(null, result.length);
      }
    );
  },

  neighbors: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-->(n:' + collP + ') RETURN n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        if (result.length === undefined) cb(null, 1);
        else cb(null, result.length);
      }
    );
  },

  neighbors2: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-[*1..2]->(n:' + collP + ') RETURN DISTINCT n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        if (result.map === undefined) {
          result = [result['n._key']];
        }
        else {
          result = result.map(function (x) { return x['n._key']; });
        }

        if (result.indexOf('P/' + id) === -1) {
          cb(null, result.length);
        }
        else {
          cb(null, result.length - 1);
        }
      }
    );
  },

  neighbors3: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-[*1..2]->(n:' + collP + ') RETURN DISTINCT n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        result = result.map(function (x) { return x['n._key']; });

        if (result.indexOf('P/' + id) === -1) {
          cb(null, result.length);
        }
        else {
          cb(null, result.length - 1);
        }
      }
    );
  },

  shortestPath: function (db, collP, collR, path, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{from}}),(t:' + collP + ' {_key:{to}}), p = shortestPath((s)-[*..15]->(t)) RETURN p',
      {from: 'P/' + path.from, to: 'P/' + path.to},
      function (err, result) {
        if (err) return cb(err);

        cb(null, result[0].length);
      }
    );
  }
};
<commit_msg>added warmup phase for JIT as suggested by Jacob Hansson<commit_after>'use strict';

module.exports = {
  name: 'Neo4J',

  startup: function (host, cb) {
    var neo4j = require('seraph')({
      server: 'http://' + host + ':7474',
      user: 'neo4j',
      pass: 'abc'
    });

    cb(neo4j);
  },

  warmup: function (db, cb) {
    module.exports.getCollection(db, 'profiles', function (err, coll) {
      if (err) return cb(err);

      module.exports.aggregate(db, coll, function (err, result) {
        if (err) return cb(err);

        var count = 0;

        for (var i = 1; i <= 50; ++i) {
          for (var j = 51; j <= 100; ++j) {
            module.exports.shortestPath(db, 'profiles', 'relations',
                                        {from: String(i), to: String(j)}, i,
                                        function (err) {
                                          if (err) return cb(err);
                                          ++count;

                                          if (count % 100 === 0) {
                                            console.log('warming up', count);
                                          }

                                          if (count === 2500) {
                                            console.log('INFO warmup done');

                                            return cb(null);
                                          }
                                        });
          }
        }
      });
    });
  },

  getCollection: function (db, name, cb) {
    cb(null, name.toUpperCase());
  },

  dropCollection: function (db, name, cb) {
    name = name.toUpperCase();

    db.nodesWithLabel(name, function (err, results) {
      if (err) cb(err);

      console.log('INFO clearing %d documents in %s', results.length, name);

      var i = -1;
      var next = function (err) {
        // if (err) console.log('ERROR %s', err);
        if (err) cb(err);

        ++i;

        if (i === results.length) {
          cb();
        }
        else {
          var obj = {id: results[i].id};
          db.delete(obj, function (err) {
            next(err);
          });
        }
      };

      next();
    });
  },

  createCollection: function (db, name, cb) {
    cb();
  },

  getDocument: function (db, coll, id, cb) {
    var obj = {_key: 'P/' + id};
    db.find(obj, false, coll, cb);
  },

  saveDocument: function (db, coll, doc, cb) {
    db.save(doc, coll, cb);
  },

  aggregate: function (db, coll, cb) {
    db.query('MATCH (f:' + coll + ') WITH f.AGE as AGE RETURN AGE, count(*)',
      function (err, result) {
        if (err) return cb(err);

        cb(null, result.length);
      }
    );
  },

  neighbors: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-->(n:' + collP + ') RETURN n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        if (result.length === undefined) cb(null, 1);
        else cb(null, result.length);
      }
    );
  },

  neighbors2: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-[*1..2]->(n:' + collP + ') RETURN DISTINCT n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        if (result.map === undefined) {
          result = [result['n._key']];
        }
        else {
          result = result.map(function (x) { return x['n._key']; });
        }

        if (result.indexOf('P/' + id) === -1) {
          cb(null, result.length);
        }
        else {
          cb(null, result.length - 1);
        }
      }
    );
  },

  neighbors3: function (db, collP, collR, id, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{key}})-[*1..2]->(n:' + collP + ') RETURN DISTINCT n._key', {key: 'P/' + id},
      function (err, result) {
        if (err) return cb(err);

        result = result.map(function (x) { return x['n._key']; });

        if (result.indexOf('P/' + id) === -1) {
          cb(null, result.length);
        }
        else {
          cb(null, result.length - 1);
        }
      }
    );
  },

  shortestPath: function (db, collP, collR, path, i, cb) {
    db.query('MATCH (s:' + collP + ' {_key:{from}}),(t:' + collP + ' {_key:{to}}), p = shortestPath((s)-[*..15]->(t)) RETURN p',
      {from: 'P/' + path.from, to: 'P/' + path.to},
      function (err, result) {
        if (err) return cb(err);

        if (result.length === 0) { return cb(null, 0); }
        else { return cb(null, result[0].length); }
      }
    );
  }
};
<|endoftext|>


<commit_before>export default function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}<commit_msg>[fix] shortened reduxReducer horizontally<commit_after>function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}
export default counter;<|endoftext|>


<commit_before>// ********MOVE SICO CODE HERE********

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses *** here I've changed the expression ***
        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return this
            .replace(urlPattern, '$&')
            .replace(pseudoUrlPattern, '$1$2')
            .replace(emailAddressPattern, '$1');
    };
}
var results = []

var clearResults = function() {
		results = null;
		results = [];
};

var upcValue = function() {
    // var str = document.getElementById("upc-value").innerHTML;
    var str = document.getElementById("upc-value").value = "UPC:";
    var txt = str.replace("UPC:", ("UPC: " + results[0].UPC));
    document.getElementById("upc-value").innerHTML = txt;
};

var asinValue = function() {
    //var str = document.getElementById("asin-value").innerHTML;
    var str = document.getElementById("asin-value").value = "ASIN:";
    var txt = str.replace("ASIN:", ("ASIN: " + results[0].ASIN));
    document.getElementById("asin-value").innerHTML = txt;
};

var asinLink = function() {
    // var str = document.getElementById("asin-link").innerHTML;
    var str = document.getElementById("asin-link").value = "enter upc or asin";
    var txt = str.replace("enter upc or asin", "http://fcresearch-na.aka.amazon.com/LAX6/results?s="+results[0].ASIN).linkify();
    document.getElementById("asin-link").innerHTML = txt;
};

var notSioc = function() {
    // var str = document.getElementById("asin-link").innerHTML;
    var str = document.getElementById("asin-link").value = "enter upc or asin";
    var txt = str.replace("enter upc or asin", "This Item is Not SIOC");
    document.getElementById("asin-link").innerHTML = txt;
    var asnstr = document.getElementById("upc-value").value = "";
    document.getElementById("upc-value").innerHTML = upcstr;
    var upcstr = document.getElementById("upc-value").value = "";
    document.getElementById("asin-value").innerHTML = asnstr;
};

function checkSioc(toSearch) {
   // var toSearch = $('#sioc-input').val()
for(var i=0; i<siocObjects.length; i++) {
  for(key in siocObjects[i]) {
    if(siocObjects[i][key].indexOf(toSearch)!=-1) {
      results.push(siocObjects[i]);
    }
  }
}
return results[0];
};

$('#check-sioc').click(function(event) {
   //alert(JSON.stringify(checkSioc($('#sioc-input').val().toString())));
   siocInput = $('#sioc-input').val().replace(/^0+/, '')
   checkSioc(siocInput);
   if (results.length == 0) {
   	notSioc();
   	$('#val-img').attr('src', 'images/no.png')
   } else {
   	asinLink();
   	upcValue();
   	asinValue();
   	$('#val-img').attr('src', 'images/yes.png')
   };
   	clearResults();
   		 //alert(results[0].UPC);
   	return false;
});
// 645729415164

<commit_msg>create alert for no sioc value<commit_after>// ********MOVE SICO CODE HERE********

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses *** here I've changed the expression ***
        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return this
            .replace(urlPattern, '$&')
            .replace(pseudoUrlPattern, '$1$2')
            .replace(emailAddressPattern, '$1');
    };
}
var results = []

var clearResults = function() {
		results = null;
		results = [];
};

var upcValue = function() {
    // var str = document.getElementById("upc-value").innerHTML;
    var str = document.getElementById("upc-value").value = "UPC:";
    var txt = str.replace("UPC:", ("UPC: " + results[0].UPC));
    document.getElementById("upc-value").innerHTML = txt;
};

var asinValue = function() {
    //var str = document.getElementById("asin-value").innerHTML;
    var str = document.getElementById("asin-value").value = "ASIN:";
    var txt = str.replace("ASIN:", ("ASIN: " + results[0].ASIN));
    document.getElementById("asin-value").innerHTML = txt;
};

var asinLink = function() {
    // var str = document.getElementById("asin-link").innerHTML;
    var str = document.getElementById("asin-link").value = "enter upc or asin";
    var txt = str.replace("enter upc or asin", "http://fcresearch-na.aka.amazon.com/LAX6/results?s="+results[0].ASIN).linkify();
    document.getElementById("asin-link").innerHTML = txt;
};

var notSioc = function() {
    // var str = document.getElementById("asin-link").innerHTML;
    var str = document.getElementById("asin-link").value = "enter upc or asin";
    var txt = str.replace("enter upc or asin", "This Item is Not SIOC");
    document.getElementById("asin-link").innerHTML = txt;
    var asnstr = document.getElementById("upc-value").value = "";
    document.getElementById("upc-value").innerHTML = upcstr;
    var upcstr = document.getElementById("upc-value").value = "";
    document.getElementById("asin-value").innerHTML = asnstr;
};

function checkSioc(toSearch) {
   // var toSearch = $('#sioc-input').val()

   if (siocInput.length == 0)
    {
     alert("Enter a UPC or ASIN")
}else{
for(var i=0; i<siocObjects.length; i++) {
  for(key in siocObjects[i]) {
    if(siocObjects[i][key].indexOf(toSearch)!=-1) {
      results.push(siocObjects[i]);
    }
  }
}
return results[0];
}
};

$('#check-sioc').click(function(event) {
   //alert(JSON.stringify(checkSioc($('#sioc-input').val().toString())));
   siocInput = $('#sioc-input').val().replace(/^0+/, '')
   checkSioc(siocInput);
   if (results.length == 0) {
   	notSioc();
   	$('#val-img').attr('src', 'images/no.png')
   } else {
   	asinLink();
   	upcValue();
   	asinValue();
   	$('#val-img').attr('src', 'images/yes.png')
   };
   	clearResults();
   		 //alert(results[0].UPC);
   	return false;
});
// 645729415164

<|endoftext|>