<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2021
 */

import moment from 'moment';
import { ToastAndroid } from 'react-native';
import { PermissionSelectors } from '../selectors/permission';
import { selectScannedSensors } from '../selectors/vaccine';
import { PermissionActions } from './PermissionActions';
import BleService from '../bluetooth/BleService';
import TemperatureLogManager from '../bluetooth/TemperatureLogManager';
import { syncStrings } from '../localization/index';
import { UIDatabase } from '../database';
import { VACCINE_CONSTANTS } from '../utilities/modules/vaccines/index';
import { VACCINE_ENTITIES } from '../utilities/modules/vaccines/constants';

export const VACCINE_ACTIONS = {
  DOWNLOAD_LOGS_START: 'Vaccine/downloadLogsStart',
  DOWNLOAD_LOGS_ERROR: 'Vaccine/downloadLogsError',
  DOWNLOAD_LOGS_COMPLETE: 'Vaccine/downloadLogsComplete',
  SCAN_START: 'Vaccine/sensorScanStart',
  SCAN_STOP: 'Vaccine/sensorScanStop',
  SENSOR_FOUND: 'Vaccine/sensorFound',
  BLINK: 'Vaccine/blinkSensor',
};

const scanStart = () => ({ type: VACCINE_ACTIONS.SCAN_START });
const scanStop = () => ({ type: VACCINE_ACTIONS.SCAN_STOP });
const sensorFound = macAddress => ({ type: VACCINE_ACTIONS.SENSOR_FOUND, payload: { macAddress } });
const downloadLogsStart = () => ({
  type: VACCINE_ACTIONS.DOWNLOAD_LOGS_START,
});
// const downloadLogsError = () => ({ type: VACCINE_ACTIONS.DOWNLOAD_LOGS_ERROR });
const downloadLogsComplete = macAddress => ({
  type: VACCINE_ACTIONS.DOWNLOAD_LOGS_COMPLETE,
  payload: { macAddress },
});

const downloadAllLogs = () => async dispatch => {
  dispatch(downloadLogsStart());

  // TEST CODE
  const sensor = {
    id: 'Hufflepuff Sensor One',
    macAddress: 'E7:6F:FC:15:13:F2',
    logInterval: 1800,
    location: { id: 'Hufflepuff location' },
  };
  const sensors = [sensor];

  sensors.forEach(async () => {
    await dispatch(downloadLogsFromSensor(sensor));
  });

  dispatch(downloadLogsComplete());
  return null;
};

const downloadLogsFromSensor = sensor => async () => {
  const { macAddress, logInterval } = sensor;

  const downloadedLogsResult =
    (await BleService().downloadLogsWithRetries(
      macAddress,
      VACCINE_CONSTANTS.MAX_BLUETOOTH_COMMAND_ATTEMPTS
    )) ?? {};

  if (downloadedLogsResult) {
    const savedTemperatureLogs = UIDatabase.objects(VACCINE_ENTITIES.TEMPERATURE_LOG)
      .filtered('sensor.macAddress == $0', macAddress)
      .sorted('timestamp', true);

    const [mostRecentLog] = savedTemperatureLogs;
    const mostRecentLogTime = mostRecentLog ? mostRecentLog.timestamp : null;
    const nextPossibleLogTime = moment(mostRecentLogTime).add(logInterval, 's');

    const numberOfLogsToSave = await TemperatureLogManager().calculateNumberOfLogsToSave(
      logInterval,
      nextPossibleLogTime
    );

    const temperatureLogs = await TemperatureLogManager().createLogs(
      downloadedLogsResult,
      sensor,
      numberOfLogsToSave,
      mostRecentLogTime
    );
    await TemperatureLogManager().saveLogs(temperatureLogs);
  }

  // TODO: Figure out what to do if an error happens. Just ignore??
  // const { code = '' } = error;
  // dispatch(downloadLogsError(code));
  return null;
};

/**
 * Helper wrapper which will check permissions for
 * bluetooth & location services before calling the supplied function
 * @param {Func} dispatch
 * @param {Func} getState
 * @param {Func} func method to run if permissions are enabled
 */
const withPermissions = async (dispatch, getState, func) => {
  const state = getState();
  const bluetoothEnabled = PermissionSelectors.bluetooth(state);
  const locationPermission = PermissionSelectors.location(state);

  // Ensure the correct permissions before initiating a new sync process.
  if (!bluetoothEnabled) await dispatch(PermissionActions.requestBluetooth());
  if (!locationPermission) await dispatch(PermissionActions.requestLocation());

  if (!bluetoothEnabled) {
    ToastAndroid.show(syncStrings.bluetooth_disabled, ToastAndroid.LONG);
    return null;
  }

  if (!locationPermission) {
    ToastAndroid.show(syncStrings.location_permission, ToastAndroid.LONG);
    return null;
  }

  return func(dispatch, state);
};

const blinkSensor = macAddress => () => {
  BleService().blinkWithRetries(macAddress, 3);
};

const scanForSensors = (dispatch, state) => {
  dispatch(scanStart());

  const deviceCallback = device => {
    const { id: macAddress } = device;
    if (macAddress) {
      const alreadyScanned = selectScannedSensors(state);
      const alreadySaved = UIDatabase.get('Sensor', macAddress, 'macAddress');

      if (!alreadyScanned?.includes(macAddress) && !alreadySaved) {
        dispatch(sensorFound(macAddress));
      }
    }
  };

  // Scan will continue running until it is stopped...
  BleService().scanForSensors(deviceCallback);
};

const startSensorBlink = macAddress => async (dispatch, getState) => {
  await withPermissions(dispatch, getState, blinkSensor(macAddress));
  return null;
};

const startSensorScan = () => async (dispatch, getState) => {
  withPermissions(dispatch, getState, scanForSensors);
  return null;
};

const stopSensorScan = () => dispatch => {
  dispatch(scanStop());
  BleService().stopScan();
};

export const VaccineActions = {
  downloadAllLogs,
  startSensorBlink,
  startSensorScan,
  stopSensorScan,
};
<commit_msg>Update to use withPermissions and constant<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2021
 */

import moment from 'moment';
import { ToastAndroid } from 'react-native';
import { PermissionSelectors } from '../selectors/permission';
import { selectScannedSensors } from '../selectors/vaccine';
import { PermissionActions } from './PermissionActions';
import BleService from '../bluetooth/BleService';
import TemperatureLogManager from '../bluetooth/TemperatureLogManager';
import { syncStrings } from '../localization/index';
import { UIDatabase } from '../database';
import { VACCINE_CONSTANTS } from '../utilities/modules/vaccines/index';
import { VACCINE_ENTITIES } from '../utilities/modules/vaccines/constants';

export const VACCINE_ACTIONS = {
  DOWNLOAD_LOGS_START: 'Vaccine/downloadLogsStart',
  DOWNLOAD_LOGS_ERROR: 'Vaccine/downloadLogsError',
  DOWNLOAD_LOGS_COMPLETE: 'Vaccine/downloadLogsComplete',
  SCAN_START: 'Vaccine/sensorScanStart',
  SCAN_STOP: 'Vaccine/sensorScanStop',
  SENSOR_FOUND: 'Vaccine/sensorFound',
  BLINK: 'Vaccine/blinkSensor',
};

const scanStart = () => ({ type: VACCINE_ACTIONS.SCAN_START });
const scanStop = () => ({ type: VACCINE_ACTIONS.SCAN_STOP });
const sensorFound = macAddress => ({ type: VACCINE_ACTIONS.SENSOR_FOUND, payload: { macAddress } });
const downloadLogsStart = () => ({
  type: VACCINE_ACTIONS.DOWNLOAD_LOGS_START,
});
// const downloadLogsError = () => ({ type: VACCINE_ACTIONS.DOWNLOAD_LOGS_ERROR });

const downloadLogsComplete = macAddress => ({
  type: VACCINE_ACTIONS.DOWNLOAD_LOGS_COMPLETE,
  payload: { macAddress },
});

const downloadAllLogs = () => async dispatch => {
  dispatch(downloadLogsStart());

  // TEST CODE
  const sensor = {
    id: 'Hufflepuff Sensor One',
    macAddress: 'E7:6F:FC:15:13:F2',
    logInterval: 1800,
    location: { id: 'Hufflepuff location' },
  };
  const sensors = [sensor];

  sensors.forEach(async () => {
    await dispatch(downloadLogsFromSensor(sensor));
  });

  dispatch(downloadLogsComplete());
  return null;
};

const downloadLogsFromSensor = sensor => async () => {
  const { macAddress, logInterval } = sensor;

  const downloadedLogsResult =
    (await BleService().downloadLogsWithRetries(
      macAddress,
      VACCINE_CONSTANTS.MAX_BLUETOOTH_COMMAND_ATTEMPTS
    )) ?? {};

  if (downloadedLogsResult) {
    const savedTemperatureLogs = UIDatabase.objects(VACCINE_ENTITIES.TEMPERATURE_LOG)
      .filtered('sensor.macAddress == $0', macAddress)
      .sorted('timestamp', true);

    const [mostRecentLog] = savedTemperatureLogs;
    const mostRecentLogTime = mostRecentLog ? mostRecentLog.timestamp : null;
    const nextPossibleLogTime = moment(mostRecentLogTime).add(logInterval, 's');

    const numberOfLogsToSave = await TemperatureLogManager().calculateNumberOfLogsToSave(
      logInterval,
      nextPossibleLogTime
    );

    const temperatureLogs = await TemperatureLogManager().createLogs(
      downloadedLogsResult,
      sensor,
      numberOfLogsToSave,
      mostRecentLogTime
    );

    console.log(temperatureLogs);
    await TemperatureLogManager().saveLogs(temperatureLogs);
  }

  // TODO: Figure out what to do if an error happens. Just ignore??
  // const { code = '' } = error;
  // dispatch(downloadLogsError(code));
  return null;
};

/**
 * Helper wrapper which will check permissions for
 * bluetooth & location services before calling the supplied function
 * @param {Func} dispatch
 * @param {Func} getState
 * @param {Func} func method to run if permissions are enabled
 */
const withPermissions = async (dispatch, getState, func) => {
  const state = getState();
  const bluetoothEnabled = PermissionSelectors.bluetooth(state);
  const locationPermission = PermissionSelectors.location(state);

  // Ensure the correct permissions before initiating a new sync process.
  if (!bluetoothEnabled) await dispatch(PermissionActions.requestBluetooth());
  if (!locationPermission) await dispatch(PermissionActions.requestLocation());

  if (!bluetoothEnabled) {
    ToastAndroid.show(syncStrings.bluetooth_disabled, ToastAndroid.LONG);
    return null;
  }

  if (!locationPermission) {
    ToastAndroid.show(syncStrings.location_permission, ToastAndroid.LONG);
    return null;
  }

  return func(dispatch, state);
};

const blinkSensor = macAddress => () => {
  BleService().blinkWithRetries(macAddress, VACCINE_CONSTANTS.MAX_BLUETOOTH_COMMAND_ATTEMPTS);
};

const scanForSensors = (dispatch, state) => {
  dispatch(scanStart());

  const deviceCallback = device => {
    const { id: macAddress } = device;
    if (macAddress) {
      const alreadyScanned = selectScannedSensors(state);
      const alreadySaved = UIDatabase.get('Sensor', macAddress, 'macAddress');

      if (!alreadyScanned?.includes(macAddress) && !alreadySaved) {
        dispatch(sensorFound(macAddress));
      }
    }
  };

  // Scan will continue running until it is stopped...
  BleService().scanForSensors(deviceCallback);
};

const startDownloadAllLogs = macAddress => async (dispatch, getState) => {
  await withPermissions(dispatch, getState, downloadAllLogs(macAddress));
  return null;
};

const startSensorBlink = macAddress => async (dispatch, getState) => {
  await withPermissions(dispatch, getState, blinkSensor(macAddress));
  return null;
};

const startSensorScan = () => async (dispatch, getState) => {
  withPermissions(dispatch, getState, scanForSensors);
  return null;
};

const stopSensorScan = () => dispatch => {
  dispatch(scanStop());
  BleService().stopScan();
};

export const VaccineActions = {
  startDownloadAllLogs,
  startSensorBlink,
  startSensorScan,
  stopSensorScan,
};
<|endoftext|>


<commit_before>var https = require('https');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var statusUrl = 'https://api.sistemium.com/status?json';
var statusUrlFull = 'https://api.sistemium.com/status?json&full';
var urlSt = statusUrlFull;

var lastData, interval, clientCount = 0;

var Status = function () {
  var self = this;

  this.on('subscribe', function () {
    interval = interval || setInterval(refreshData, 1000);
    clientCount++;
    console.log('subscribe, clientCount:', clientCount);
  });

  this.on('subscribe-full', function () {
    interval = interval || setInterval(refreshData, 1000);
    clientCount++;
    console.log('subscribe-full, clientCount:', clientCount);
  });

  this.on('unsubscribe', function () {
    if (!--clientCount) {
      clearInterval(interval);
      interval = undefined;
      console.log('interval cleared');
    }
    console.log('unsubscribe, clientCount:', clientCount);
  });

  function refreshData () {
    https.get(statusUrl, function(res) {

      var body = '';

      res.on('data', function (chunk) {
        body += chunk;
      });

      res.on('end', function () {
        var jsonData = JSON.parse(body);
        //console.log('Got response: ', jsonData);
        lastData = jsonData;
        self.emit('data', jsonData);
      });

    }).on('error', function(e) {
      console.log('Got error: ', e);
    });
  }
};

util.inherits(Status, EventEmitter);
module.exports = Status;
<commit_msg>client disconnect logic changed<commit_after>var https = require('https');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var statusUrl = 'https://api.sistemium.com/status?json';
var statusUrlFull = 'https://api.sistemium.com/status?json&full';
var urlSt = statusUrlFull;

var lastData, interval, clientCount = 0;

var Status = function () {
  var self = this;

  this.on('subscribe', function () {
    interval = interval || setInterval(refreshData, 1000);
    clientCount++;
    console.log('subscribe, clientCount:', clientCount);
  });

  this.on('subscribe-full', function () {
    interval = interval || setInterval(refreshData, 1000);
    clientCount++;
    console.log('subscribe-full, clientCount:', clientCount);
  });

  this.on('unsubscribe', function () {
    if (--clientCount<=0) {
      clientCount = 0;
      clearInterval(interval);
      interval = undefined;
      console.log('interval cleared');
    }
    console.log('unsubscribe, clientCount:', clientCount);
  });

  function refreshData () {
    https.get(statusUrl, function(res) {

      var body = '';

      res.on('data', function (chunk) {
        body += chunk;
      });

      res.on('end', function () {
        var jsonData = JSON.parse(body);
        //console.log('Got response: ', jsonData);
        lastData = jsonData;
        self.emit('data', jsonData);
      });

    }).on('error', function(e) {
      console.log('Got error: ', e);
    });
  }
};

util.inherits(Status, EventEmitter);
module.exports = Status;
<|endoftext|>


<commit_before>import heroes from 'dotaconstants/build/heroes.json';
import immutable from 'seamless-immutable';
import flatten from 'lodash/fp/flatten';
import {
  isRadiant,
  isSupport,
  getLevelFromXp,
  unpackPositionData,
} from '../utility';
import analyzeMatch from './analyzeMatch';
import store from '../store';

let expandedUnitNames = null;

function generateExpandedUnitNames(strings) {
  const expanded = {};
  Object.keys(strings)
    .filter(str => str.indexOf('npc_dota_') === 0)
    .forEach((key) => {
      // Currently, no unit goes up higher than 4
      for (let i = 1; i < 5; i += 1) {
        expanded[key.replace('#', i)] = strings[key];
      }
    });
  return expanded;
}

const getMaxKeyOfObject = field => Number(Object.keys(field || {}).sort((a, b) => Number(b) - Number(a))[0]) || 0;

function generateTeamfights({ players, teamfights = [] }) {
  const computeTfData = (tf) => {
    const newtf = {
      ...tf,
      deaths_pos: [],
      radiant_gold_advantage_delta: 0,
      radiant_gold_delta: 0,
      dire_gold_delta: 0,
      radiant_xp_delta: 0,
      radiant_participation: 0,
      radiant_deaths: 0,
      dire_participation: 0,
      dire_deaths: 0,
    };
    newtf.players = players.map((player) => {
      const tfplayer = tf.players[player.player_slot % (128 - 5)];
      if (!tfplayer) {
        return null;
      }
      if (isRadiant(player.player_slot)) {
        newtf.radiant_gold_advantage_delta += tfplayer.gold_delta;
        newtf.radiant_gold_delta += tfplayer.gold_delta;
        newtf.radiant_xp_delta += tfplayer.xp_delta;
        newtf.radiant_participation += tfplayer.participate ? 1 : 0;
        newtf.radiant_deaths += tfplayer.deaths ? 1 : 0;
      } else {
        newtf.radiant_gold_advantage_delta -= tfplayer.gold_delta;
        newtf.dire_gold_delta -= tfplayer.gold_delta;
        newtf.radiant_xp_delta -= tfplayer.xp_delta;
        newtf.dire_participation += tfplayer.participate ? 1 : 0;
        newtf.dire_deaths += tfplayer.deaths ? 1 : 0;
      }
      const playerDeathsPos = unpackPositionData(tfplayer.deaths_pos)
        .map(deathPos => ({
          ...deathPos,
          isRadiant: isRadiant(player.player_slot),
          player,
        }));
      newtf.deaths_pos = newtf.deaths_pos.concat(playerDeathsPos);
      return {
        ...player,
        ...tfplayer,
        participate: tfplayer.deaths > 0 || tfplayer.damage > 0, // || tfplayer.healing > 0,
        level_start: getLevelFromXp(tfplayer.xp_start),
        level_end: getLevelFromXp(tfplayer.xp_end),
        deaths_pos: playerDeathsPos,
      };
    }).filter(player => (player !== null));

    // We have to do this after we process the stuff so that we will have the player in
    // the data instead of just the 'teamfight player' which doesn't have enough data.
    newtf.deaths_pos = newtf.deaths_pos
      .map(death => ([{
        ...death,
        killer: newtf.players
          .find(killer => heroes[death.player.hero_id] && killer.killed[heroes[death.player.hero_id].name]),
      }]))
      .reduce(
        (newDeathsPos, death) => {
          const copy = [...newDeathsPos];
          const samePosition = copy
            .findIndex((deathPos) => {
              const cursor = deathPos[0];
              return cursor.x === death[0].x && cursor.y === death[0].y;
            });
          if (samePosition !== -1) {
            copy[samePosition] = copy[samePosition].concat(death);
          } else {
            copy.push(death);
          }
          return copy;
        },
        [],
      );
    return newtf;
  };
  return (teamfights || []).map(computeTfData);
}

// create a detailed history of each wards
function generateVisionLog(match) {
  const computeWardData = (player, i) => {
    // let's coerce some value to be sure the structure is what we expect.
    const safePlayer = {
      ...player,
      obs_log: player.obs_log || [],
      sen_log: player.sen_log || [],
      obs_left_log: player.obs_left_log || [],
      sen_left_log: player.sen_left_log || [],
    };

    // let's zip the *_log and the *_left log in a 2-tuples
    const extractVisionLog = (type, enteredLog, leftLog) =>
      enteredLog.map((e) => {
        const wards = [e, leftLog.find(l => l.ehandle === e.ehandle)];
        return {
          player: i,
          key: wards[0].ehandle,
          type,
          entered: wards[0],
          left: wards[1],
        };
      });
    const observers = extractVisionLog('observer', safePlayer.obs_log, safePlayer.obs_left_log);
    const sentries = extractVisionLog('sentry', safePlayer.sen_log, safePlayer.sen_left_log);
    return observers.concat(sentries);
  };

  const temp = flatten((match.players || []).map(computeWardData));
  temp.sort((a, b) => a.entered.time - b.entered.time);
  const result2 = temp.map((x, i) => ({ ...x, key: i }));

  return result2;
}

function transformMatch(m) {
  const { strings } = store.getState().app;
  const newPlayers = m.players.map((player) => {
    const newPlayer = {
      ...player,
      desc: [strings[`lane_role_${player.lane_role}`], isSupport(player) ? 'Support' : 'Core'].join('/'),
      multi_kills_max: getMaxKeyOfObject(player.multi_kills),
      kill_streaks_max: getMaxKeyOfObject(player.kill_streaks),
      lh_ten: (player.lh_t || [])[10],
      dn_ten: (player.dn_t || [])[10],
      analysis: analyzeMatch(m, player),
    };
    // filter interval data to only be >= 0
    if (player.times) {
      const intervals = ['lh_t', 'gold_t', 'xp_t', 'times'];
      intervals.forEach((key) => {
        newPlayer[key] = player[key].filter((el, i) => player.times[i] >= 0);
      });
    }
    // compute damage to towers/rax/roshan
    if (player.damage) {
      // npc_dota_goodguys_tower2_top
      // npc_dota_goodguys_melee_rax_top
      // npc_dota_roshan
      // npc_dota_neutral_giant_wolf
      // npc_dota_creep
      newPlayer.objective_damage = {};
      Object.keys(player.damage).forEach((key) => {
        let identifier = null;
        if (key.indexOf('tower') !== -1) {
          identifier = key.split('_').slice(3).join('_');
        }
        if (key.indexOf('rax') !== -1) {
          identifier = key.split('_').slice(4).join('_');
        }
        if (key.indexOf('roshan') !== -1) {
          identifier = 'roshan';
        }
        if (key.indexOf('fort') !== -1) {
          identifier = 'fort';
        }
        if (key.indexOf('healers') !== -1) {
          identifier = 'shrine';
        }
        newPlayer.objective_damage[identifier] = newPlayer.objective_damage[identifier] ?
          newPlayer.objective_damage[identifier] + player.damage[key] :
          player.damage[key];
      });
    }
    if (player.killed) {
      newPlayer.specific = {};
      // expand keys in specific by # (1-4)
      // map to friendly name
      // iterate through keys in killed
      // if in expanded, put in pm.specific
      if (!expandedUnitNames) {
        expandedUnitNames = generateExpandedUnitNames(strings);
      }
      Object.keys(player.killed).forEach((key) => {
        if (key in expandedUnitNames) {
          const name = expandedUnitNames[key];
          newPlayer.specific[name] = newPlayer.specific[name] ? newPlayer.specific[name] + newPlayer.killed[key] : newPlayer.killed[key];
        }
      });
    }
    if (player.purchase) {
      newPlayer.purchase_tpscroll = player.purchase.tpscroll;
      newPlayer.purchase_ward_observer = player.purchase.ward_observer;
      newPlayer.purchase_ward_sentry = player.purchase.ward_sentry;
      newPlayer.purchase_smoke_of_deceit = player.purchase.smoke_of_deceit;
      newPlayer.purchase_dust = player.purchase.dust;
      newPlayer.purchase_gem = player.purchase.gem;
    }
    newPlayer.buybacks = (player.buyback_log || []).length;
    newPlayer.total_gold = (player.gold_per_min * m.duration) / 60;
    if (m.game_mode === 18 && Object.prototype.hasOwnProperty.call(player, 'ability_upgrades_arr')) {
      const arr = [];
      player.ability_upgrades_arr.forEach((ability) => {
        if (!arr.includes(ability) && ability < 5900) {
          arr.push(ability);
        }
      });
      newPlayer.abilities = arr;
    }
    return newPlayer;
  });

  const newObjectives = (m.objectives || []).map((obj) => {
    if (obj.slot > 0) {
      return {
        ...obj,
        player_slot: obj.slot > 4 ? obj.slot + 123 : obj.slot,
      };
    }
    return {
      ...obj,
    };
  });

  return {
    ...m,
    teamfights: generateTeamfights(m),
    players: newPlayers,
    wards_log: generateVisionLog(immutable(m)),
    objectives: newObjectives,
  };
}

export default transformMatch;
<commit_msg>Add the comments back.<commit_after>import heroes from 'dotaconstants/build/heroes.json';
import immutable from 'seamless-immutable';
import flatten from 'lodash/fp/flatten';
import {
  isRadiant,
  isSupport,
  getLevelFromXp,
  unpackPositionData,
} from '../utility';
import analyzeMatch from './analyzeMatch';
import store from '../store';

let expandedUnitNames = null;

function generateExpandedUnitNames(strings) {
  const expanded = {};
  Object.keys(strings)
    .filter(str => str.indexOf('npc_dota_') === 0)
    .forEach((key) => {
    // Currently, no unit goes up higher than 4
      for (let i = 1; i < 5; i += 1) {
        expanded[key.replace('#', i)] = strings[key];
      }
    });
  return expanded;
}

const getMaxKeyOfObject = field => Number(Object.keys(field || {}).sort((a, b) => Number(b) - Number(a))[0]) || 0;

function generateTeamfights({ players, teamfights = [] }) {
  const computeTfData = (tf) => {
    const newtf = {
      ...tf,
      deaths_pos: [],
      radiant_gold_advantage_delta: 0,
      radiant_gold_delta: 0,
      dire_gold_delta: 0,
      radiant_xp_delta: 0,
      radiant_participation: 0,
      radiant_deaths: 0,
      dire_participation: 0,
      dire_deaths: 0,
    };
    newtf.players = players.map((player) => {
      const tfplayer = tf.players[player.player_slot % (128 - 5)];
      if (!tfplayer) {
        return null;
      }
      // compute team gold/xp deltas
      if (isRadiant(player.player_slot)) {
        newtf.radiant_gold_advantage_delta += tfplayer.gold_delta;
        newtf.radiant_gold_delta += tfplayer.gold_delta;
        newtf.radiant_xp_delta += tfplayer.xp_delta;
        newtf.radiant_participation += tfplayer.participate ? 1 : 0;
        newtf.radiant_deaths += tfplayer.deaths ? 1 : 0;
      } else {
        newtf.radiant_gold_advantage_delta -= tfplayer.gold_delta;
        newtf.dire_gold_delta -= tfplayer.gold_delta;
        newtf.radiant_xp_delta -= tfplayer.xp_delta;
        newtf.dire_participation += tfplayer.participate ? 1 : 0;
        newtf.dire_deaths += tfplayer.deaths ? 1 : 0;
      }
      const playerDeathsPos = unpackPositionData(tfplayer.deaths_pos)
        .map(deathPos => ({
          ...deathPos,
          isRadiant: isRadiant(player.player_slot),
          player,
        }));
      newtf.deaths_pos = newtf.deaths_pos.concat(playerDeathsPos);
      return {
        ...player,
        ...tfplayer,
        participate: tfplayer.deaths > 0 || tfplayer.damage > 0, // || tfplayer.healing > 0,
        level_start: getLevelFromXp(tfplayer.xp_start),
        level_end: getLevelFromXp(tfplayer.xp_end),
        deaths_pos: playerDeathsPos,
      };
    }).filter(player => (player !== null));

    // We have to do this after we process the stuff so that we will have the player in
    // the data instead of just the 'teamfight player' which doesn't have enough data.
    newtf.deaths_pos = newtf.deaths_pos
      .map(death => ([{
        ...death,
        killer: newtf.players
          .find(killer => heroes[death.player.hero_id] && killer.killed[heroes[death.player.hero_id].name]),
      }]))
      .reduce(
        (newDeathsPos, death) => {
          const copy = [...newDeathsPos];
          const samePosition = copy
            .findIndex((deathPos) => {
              const cursor = deathPos[0];
              return cursor.x === death[0].x && cursor.y === death[0].y;
            });
          if (samePosition !== -1) {
            copy[samePosition] = copy[samePosition].concat(death);
          } else {
            copy.push(death);
          }
          return copy;
        },
        [],
      );
    return newtf;
  };
  return (teamfights || []).map(computeTfData);
}

// create a detailed history of each wards
function generateVisionLog(match) {
  const computeWardData = (player, i) => {
    // let's coerce some value to be sure the structure is what we expect.
    const safePlayer = {
      ...player,
      obs_log: player.obs_log || [],
      sen_log: player.sen_log || [],
      obs_left_log: player.obs_left_log || [],
      sen_left_log: player.sen_left_log || [],
    };

    // let's zip the *_log and the *_left log in a 2-tuples
    const extractVisionLog = (type, enteredLog, leftLog) =>
      enteredLog.map((e) => {
        const wards = [e, leftLog.find(l => l.ehandle === e.ehandle)];
        return {
          player: i,
          key: wards[0].ehandle,
          type,
          entered: wards[0],
          left: wards[1],
        };
      });
    const observers = extractVisionLog('observer', safePlayer.obs_log, safePlayer.obs_left_log);
    const sentries = extractVisionLog('sentry', safePlayer.sen_log, safePlayer.sen_left_log);
    return observers.concat(sentries);
  };

  const temp = flatten((match.players || []).map(computeWardData));
  temp.sort((a, b) => a.entered.time - b.entered.time);
  const result2 = temp.map((x, i) => ({ ...x, key: i }));

  return result2;
}

function transformMatch(m) {
  const { strings } = store.getState().app;
  const newPlayers = m.players.map((player) => {
    const newPlayer = {
      ...player,
      desc: [strings[`lane_role_${player.lane_role}`], isSupport(player) ? 'Support' : 'Core'].join('/'),
      multi_kills_max: getMaxKeyOfObject(player.multi_kills),
      kill_streaks_max: getMaxKeyOfObject(player.kill_streaks),
      lh_ten: (player.lh_t || [])[10],
      dn_ten: (player.dn_t || [])[10],
      analysis: analyzeMatch(m, player),
    };
    // filter interval data to only be >= 0
    if (player.times) {
      const intervals = ['lh_t', 'gold_t', 'xp_t', 'times'];
      intervals.forEach((key) => {
        newPlayer[key] = player[key].filter((el, i) => player.times[i] >= 0);
      });
    }
    // compute damage to towers/rax/roshan
    if (player.damage) {
      // npc_dota_goodguys_tower2_top
      // npc_dota_goodguys_melee_rax_top
      // npc_dota_roshan
      // npc_dota_neutral_giant_wolf
      // npc_dota_creep
      newPlayer.objective_damage = {};
      Object.keys(player.damage).forEach((key) => {
        let identifier = null;
        if (key.indexOf('tower') !== -1) {
          identifier = key.split('_').slice(3).join('_');
        }
        if (key.indexOf('rax') !== -1) {
          identifier = key.split('_').slice(4).join('_');
        }
        if (key.indexOf('roshan') !== -1) {
          identifier = 'roshan';
        }
        if (key.indexOf('fort') !== -1) {
          identifier = 'fort';
        }
        if (key.indexOf('healers') !== -1) {
          identifier = 'shrine';
        }
        newPlayer.objective_damage[identifier] = newPlayer.objective_damage[identifier] ?
          newPlayer.objective_damage[identifier] + player.damage[key] :
          player.damage[key];
      });
    }
    if (player.killed) {
      newPlayer.specific = {};
      // expand keys in specific by # (1-4)
      // map to friendly name
      // iterate through keys in killed
      // if in expanded, put in pm.specific
      if (!expandedUnitNames) {
        expandedUnitNames = generateExpandedUnitNames(strings);
      }
      Object.keys(player.killed).forEach((key) => {
        if (key in expandedUnitNames) {
          const name = expandedUnitNames[key];
          newPlayer.specific[name] = newPlayer.specific[name] ? newPlayer.specific[name] + newPlayer.killed[key] : newPlayer.killed[key];
        }
      });
    }
    if (player.purchase) {
      newPlayer.purchase_tpscroll = player.purchase.tpscroll;
      newPlayer.purchase_ward_observer = player.purchase.ward_observer;
      newPlayer.purchase_ward_sentry = player.purchase.ward_sentry;
      newPlayer.purchase_smoke_of_deceit = player.purchase.smoke_of_deceit;
      newPlayer.purchase_dust = player.purchase.dust;
      newPlayer.purchase_gem = player.purchase.gem;
    }
    newPlayer.buybacks = (player.buyback_log || []).length;
    newPlayer.total_gold = (player.gold_per_min * m.duration) / 60;
    if (m.game_mode === 18 && Object.prototype.hasOwnProperty.call(player, 'ability_upgrades_arr')) {
      const arr = [];
      player.ability_upgrades_arr.forEach((ability) => {
        if (!arr.includes(ability) && ability < 5900) {
          arr.push(ability);
        }
      });
      newPlayer.abilities = arr;
    }
    return newPlayer;
  });

  const newObjectives = (m.objectives || []).map((obj) => {
    if (obj.slot > 0) {
      return {
        ...obj,
        player_slot: obj.slot > 4 ? obj.slot + 123 : obj.slot,
      };
    }
    return {
      ...obj,
    };
  });

  return {
    ...m,
    teamfights: generateTeamfights(m),
    players: newPlayers,
    wards_log: generateVisionLog(immutable(m)),
    objectives: newObjectives,
  };
}

export default transformMatch;
<|endoftext|>


<commit_before>import Vue from 'vue';

import './bootstrap';

new Vue({
  el: '#app',
  template: `

404 Not Found

Page not found. Back to Top Page.

      <page-footer></page-footer>

  `,
});
<commit_msg>Remove empty line of 404.js<commit_after>import Vue from 'vue';
import './bootstrap';

new Vue({
  el: '#app',
  template: `

404 Not Found

Page not found. Back to Top Page.

      <page-footer></page-footer>

  `,
});
<|endoftext|>


<commit_before>app.controller("registraQueixa", function ($scope, $http, toastr, $location) {

    $scope.registerComplaint = function (complaint) {
        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/",
            JSON.stringify(complaint)).then(function success(response) {
            toastr.success("Queixa adicionada com sucesso!");
            $location.path('/createdcomplaint/' + response.data.id);
        }, function error(error) {
            alert("Problemas ao tentar adicionar queixa.");
        });
    }
});

app.controller("atualizaQueixa", function ($scope, $http, toastr, $location) {

    $scope.atualizarQueixa = function (complaint) {
        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id,
            JSON.stringify(complaint)).then(function success(response) {
            toastr.success("Queixa atualizada com sucesso!");
            $location.path('/updatedcomplaint/' + response.data.id);
        }, function error(error) {
            alert("Problemas ao tentar atualizar queixa.");
        });
    }
});

app.controller("procuraQueixa", function ($scope, $http) {

    $scope.complaint;
    $scope.searchComplaint = function (id) {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id)
            .then(function successCallback(response) {
                $scope.complaint = response.data;
            }, function errorCallback(error) {
                $scope.complaint = null;
                alert("Queixa nao existe ou ID errado.")
            });
    }
});

app.controller("situacaoGeralQueixas", function ($scope, $http) {

    $scope.situation = "";

    var getGeneralSituationComplaints = function (neighborhood) {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/geral/situacao")
            .then(function success(response) {
                console.log(response.data);

                if (response.data == "RUIM") {
                    $scope.situation = {
                        status: "RUIM",
                        color: "label-danger"
                    };

                } else if (response.data == "REGULAR") {

                    $scope.situation = {
                        status: "REGULAR",
                        color: "label-primary"
                    };
                } else {
                    $scope.situation = "";
                    $scope.situation = {
                        status: "BOM",
                        color: "label-success"
                    };

                }
            }, function failed(error) {
                alert("Erro na busca de unidades");
            });
    }

    getGeneralSituationComplaints();
});

app.controller("mensagemCriacaoQueixa", function ($scope, $routeParams) {
    $scope.responseComplaintId = "";
    var showMessage = function () {
        $scope.responseComplaintId = $routeParams.id;
    }

    showMessage();
});

app.controller("mensagemQueixaDeletada", function ($scope, $routeParams) {
    $scope.responseComplaintId = "";
    var showMessage = function () {
        $scope.responseComplaintId = $routeParams.id;
    }

    showMessage();
});

app.controller("retornaQueixasCtrl", function ($scope, $http) {
    $scope.listaQueixas = [];
    $scope.retornaQueixas = function () {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/queixa/listarTodasQueixas").then(function sucessCallback(response) {

            $scope.listaQueixas = response.data;

        }, function errorCallback(error) {
            alert("Erro nas Queixas")
        })
    }
});

app.controller("comentaQueixaCtrl", function ($scope, $http) {

    var promise = $http.post("/queixa/{id}", usuarioCadastrado);

    $scope.comentaQueixa = function (id) {
        var comentario = prompt("Digite seu comentário:", "...");

        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id)
            .then(function sucessCallback(response) {
                response.data.obj.comentario = comentario;
            }, function errorCallback(error) {
                alert("Não há nenhuma queixa para comentar.");
            })
    }
});

app.controller("apagaQueixaCtrl", function ($scope, $http) {

    $scope.deleta = null;

    $scope.apagaQueixa = function (id) {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id)
            .then(function sucessCallback(response) {
                response.data.obj = $scope.deleta;
            }, function errorCallback(error) {
                alert("Não há nenhuma queixa para apagar.");
            })
    }

});
<commit_msg>Testes para o heroku<commit_after>app.controller("registraQueixa", function ($scope, $http, toastr, $location) {

    $scope.registerComplaint = function (complaint) {
        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/",
            JSON.stringify(complaint)).then(function success(response) {
            toastr.success("Queixa adicionada com sucesso!");
            $location.path('/createdcomplaint/' + response.data.id);
        }, function error(error) {
            alert("Problemas ao tentar adicionar queixa.");
        });
    }
});

app.controller("atualizaQueixa", function ($scope, $http, toastr, $location) {

    $scope.atualizarQueixa = function (complaint) {
        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id,
            JSON.stringify(complaint)).then(function success(response) {
            toastr.success("Queixa atualizada com sucesso!");
            $location.path('/updatedcomplaint/' + response.data.id);
        }, function error(error) {
            alert("Problemas ao tentar atualizar queixa.");
        });
    }
});

app.controller("procuraQueixa", function ($scope, $http) {

    $scope.complaint;
    $scope.searchComplaint = function (id) {
        $http.get("https://disque-saude-app-backend.herokuapp.com/DisqueSaudeApp/api/queixa/" + id)
            .then(function successCallback(response) {
                $scope.complaint = response.data;
            }, function errorCallback(error) {
                $scope.complaint = null;
                alert("Queixa nao existe ou ID errado.")
            });
    }
});

app.controller("situacaoGeralQueixas", function ($scope, $http) {

    $scope.situation = "";

    var getGeneralSituationComplaints = function (neighborhood) {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/geral/situacao")
            .then(function success(response) {
                console.log(response.data);

                if (response.data == "RUIM") {
                    $scope.situation = {
                        status: "RUIM",
                        color: "label-danger"
                    };

                } else if (response.data == "REGULAR") {

                    $scope.situation = {
                        status: "REGULAR",
                        color: "label-primary"
                    };
                } else {
                    $scope.situation = "";
                    $scope.situation = {
                        status: "BOM",
                        color: "label-success"
                    };

                }
            }, function failed(error) {
                alert("Erro na busca de unidades");
            });
    }

    getGeneralSituationComplaints();
});

app.controller("mensagemCriacaoQueixa", function ($scope, $routeParams) {
    $scope.responseComplaintId = "";
    var showMessage = function () {
        $scope.responseComplaintId = $routeParams.id;
    }

    showMessage();
});

app.controller("mensagemQueixaDeletada", function ($scope, $routeParams) {
    $scope.responseComplaintId = "";
    var showMessage = function () {
        $scope.responseComplaintId = $routeParams.id;
    }

    showMessage();
});

app.controller("retornaQueixasCtrl", function ($scope, $http) {
    $scope.listaQueixas = [];
    $scope.retornaQueixas = function () {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/queixa/listarTodasQueixas").then(function sucessCallback(response) {

            $scope.listaQueixas = response.data;

        }, function errorCallback(error) {
            alert("Erro nas Queixas")
        })
    }
});

app.controller("comentaQueixaCtrl", function ($scope, $http) {

    var promise = $http.post("/queixa/{id}", usuarioCadastrado);

    $scope.comentaQueixa = function (id) {
        var comentario = prompt("Digite seu comentário:", "...");

        $http.post("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id)
            .then(function sucessCallback(response) {
                response.data.obj.comentario = comentario;
            }, function errorCallback(error) {
                alert("Não há nenhuma queixa para comentar.");
            })
    }
});

app.controller("apagaQueixaCtrl", function ($scope, $http) {

    $scope.deleta = null;

    $scope.apagaQueixa = function (id) {
        $http.get("http://localhost:5000/DisqueSaudeApp/api/queixa/" + id)
            .then(function sucessCallback(response) {
                response.data.obj = $scope.deleta;
            }, function errorCallback(error) {
                alert("Não há nenhuma queixa para apagar.");
            })
    }

});
<|endoftext|>


<commit_before>/*
 *  things.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-01-08
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb.helpers;
var cfg = iotdb.cfg;

var mqtt = require('./mqtt');
var settings = require('./settings');
var helpers = require('./helpers');
var interactors = require('./interactors');

var bunyan = require('bunyan');
var logger = bunyan.createLogger({
    name: 'iotdb-runner',
    module: 'things',
});

/**
 *  Returns a Thing by thing_id
 */
var _get_thing = function(thing_id) {
    var iot = iotdb.iot();
    var things = iot.things()
    for (var ti = 0; ti < things.length; ti++) {
        var t = things[ti];
        if (t.thing_id() == thing_id) {
            return t
        }
    }

    console.log("# _get_thing: thing not found", thing_id)
    return null
}

var scrub_id = function(v) {
    if (!v) {
        return ""
    } else {
        return v.replace(/.*#/, '')
    }
}

var structured = {};

/**
 *  Clean up the structure. You can do this whenever
 *  you want - it will be rebuilt when need in
 *  _structure_thing. Specifically, you'll want to
 *  clear structures when the metadata changes.
 */
var _clear_structure = function(thing) {
    if (thing === undefined) {
        structured = {};
    } else {
        structured[thing.thing_id()] = undefined;
    }
}

/*
 *  Preprocess attributes
 *  - compact everything
 *  - find out if control or reading attibute
 */
var _structure_thing = function(thing) {
    var s = structured[thing.thing_id()];
    if (s) {
        return s;
    }

    var meta = thing.meta();
    var thing_name = meta.get('schema:name') || thing.name;

    /*
     *  Do initial pre-processing on attributes
     */
    var catd = {};
    var tats = thing.attributes()
    for (var tax in tats) {
        var tat = tats[tax]

        var cat = _.ld.compact(tat)
        cat._code = tat.get_code()

        var name = _.ld.first(cat, 'schema:name')
        cat['@id'] = "/api/things/" + thing.thing_id() + "/#" + cat._code;
        cat._name = name || cat._code;
        cat._thing_id = thing.thing_id();
        cat._thing_name = thing_name;
        cat._thing_group = thing_name + "@@" + thing.thing_id();
        cat._id = thing.thing_id() + "/#" + cat._code;
        cat.group = thing_name;

        var cid = scrub_id(_.ld.first(cat, "@id", ""))
        if (_.ld.list(cat, 'iot:role') === undefined) {
            cat._out = cid
            cat._in = cid
        }
        if (_.ld.contains(cat, 'iot:role', 'iot-attribute:role-control')) {
            cat._out = cid
        }
        if (_.ld.contains(cat, 'iot:role', 'iot-attribute:role-reading')) {
            cat._in = cid
        }

        catd[cid] = cat
    }

    /**
     *  Group related control/reading attributes together
     */
    for (var cid in catd) {
        var cat = catd[cid]
        if (cat._use === undefined) {
            cat._use = true
        }

        var rids = _.ld.list(cat, "iot:related-role", [])
        for (var rix in rids) {
            var rid = scrub_id(rids[rix])
            var rat = catd[rid]
            if (rat === undefined) {
                continue
            }

            if (rat._use === undefined) {
                rat._use = false
            }
            if (cat._out && !rat._out) {
                rat._out = cat._out
            }
            if (cat._in && !rat._in) {
                rat._in = cat._in
            }
        }

    }

    var cats = [];
    for (var ci in catd) {
        var cat = catd[ci];
        if (!cat._use) {
            continue;
        }

        cats.push(cat);
    }

    s = {
        thing_id: thing.thing_id(),
        cats: cats
    };
    structured[thing.thing_id()] = s;

    return s;
};

var structured = function() {
    var things = iotdb.iot().things();

    // order things by thing_name first
    var tts = [];
    for (var ti = 0; ti < things.length; ti++) {
        var thing = things[ti];
        var meta = thing.meta();
        var thing_name = meta.get('schema:name') || thing.name;
        if (thing_name === undefined) {
            continue
        }

        tts.push([ thing_name, thing ]);
    }

    tts.sort();

    // then get all the compressed attributes
    var cats = [];
    for (var ti in tts) {
        var tt = tts[ti];
        var thing = tt[1];
        var state = thing.state();
        var s = _structure_thing(thing);

        for (var ci in s.cats) {
            var cat = s.cats[ci];
            cat.state = state;

            cats.push(cat);
        }
    }

    return cats;
};

var _make_thing = function(f) {
    return function (request, response) {
        logger.info({
            method: "_make_thing",
            recipe_id: request.params.thing_id,
            body: request.body,
        }, "called");

        var thing = _get_thing(request.params.thing_id);
        if (!thing) {
            return response
                .set('Content-Type', 'application/json')
                .status(404)
                .send(JSON.stringify({
                    error: "thing not found",
                    thing_id: request.params.thing_id
                }, null, 2))
                ;
        }

        response.set('Content-Type', 'application/json');
        response.send(JSON.stringify(f(thing, request, response), null, 2));
    };
};

/**
 */
var thing_istate = function(thing) {
    return _.extend(
        thing.state({ istate: true, ostate: false }),
        {
            "@id": "/api/things/" + thing.thing_id() + "/istate",
        }
    );
};

/**
 */
var thing_ostate = function(thing) {
    return _.extend(
        thing.state({ istate: false, ostate: true }),
        {
            "@id": "/api/things/" + thing.thing_id() + "/ostate",
        }
    );
};

/**
 */
var thing_meta = function(thing) {
    return _.ld.compact(
        thing.meta().state(),
        {
            "@id": "/api/things/" + thing.thing_id() + "/meta",
        }
    );
};

/**
 */
var thing_model = function(thing) {
    var md = _.ld.compact(thing.jsonld({
        // base: "/api/things/" + thing.thing_id() + "/model",
    }));

    md["@context"] = {
        "iot": _.ld.namespace["iot"],
        "iot-unit": _.ld.namespace["iot-unit"],
        "iot-attribute": _.ld.namespace["iot-attribute"],
        "schema": _.ld.namespace["schema"],
    },
    md["@id"] = "/api/things/" + thing.thing_id() + "/model";

    var meta = thing.meta();
    md._id = thing.thing_id();
    md._name = meta.get("schema:name");

    var ads = _.ld.list(md, "iot:attribute", []);
    for (var adi in ads) {
        var ad = ads[adi];
        ad._code = ad["@id"].replace(/^.*#/, '');
        ad._control = false;
        ad._reading = false;
        ad._name = _.ld.first(ad, "schema:name");

        var roles = _.ld.list(ad, 'iot:role');
        if (!roles) {
            ad._control = true;
            ad._reading = true;
        } else {
            for (var ri in roles) {
                var role = roles[ri];
                if (role === 'iot-attribute:role-control') {
                    ad._control = true;
                } else if (role === 'iot-attribute:role-reading') {
                    ad._reading = true;
                }
            }
        }

        interactors.assign_interactor_to_attribute(ad);
    }

    return md;
};

/*
 */
var things = function() {
    var tds = [];
    var things = iotdb.iot().things();

    for (var ti = 0; ti < things.length; ti++) {
        var thing = things[ti];
        var td = {};
        var tmodel = thing_model(thing);

        td["_id"] = tmodel._id;
        td["_name"] = tmodel._name;
        td["_section"] = "things";
        td["model"] = tmodel;
        td["istate"] = thing_istate(thing);
        td["ostate"] = thing_ostate(thing);
        td["meta"] = thing_meta(thing);

        tds.push(td);
    }

    return tds;
};

/**
 *   get '/api/things/:thing_id/istate'
 */
var get_istate = _make_thing(thing_istate);

/**
 *   get '/api/things/:thing_id/ostate'
 */
var get_ostate = _make_thing(thing_ostate);

/**
 *   put '/api/things/:thing_id/ostate'
 */
var put_ostate = _make_thing(function(thing, request, response) {
    thing.update(request.body, { notify: true });

    return {};
});

/**
 *   get '/api/things/:thing_id/meta'
 */
var get_meta = _make_thing(thing_meta);

/**
 *   get '/api/things/:thing_id/model'
 */
var get_model = _make_thing(thing_model);

/**
 */
var setup = function() {
    var iot = iotdb.iot();
    var things = iot.connect();

    things.on_thing(function(thing) {
        thing.on("state", function(thing) {
            var topic = settings.d.mqttd.prefix + "api/things/" + thing.thing_id() + "/istate";
            var payload = thing_istate(thing);

            mqtt.publish(settings.d.mqttd, topic, payload);
        });
        thing.on("meta", function(thing) {
            var topic = settings.d.mqttd.prefix + "api/things/" + thing.thing_id() + "/meta";
            var payload = thing_meta(thing);

            mqtt.publish(settings.d.mqttd, topic, payload);

            // _clear_structure(thing);
            // someday publish a metadata change
        });
    });
};

/**
 *  API
 */
exports.setup = setup;

exports.get_istate = get_istate;
exports.get_ostate = get_ostate;
exports.put_ostate = put_ostate;
exports.get_meta = get_meta;
exports.get_model = get_model;

exports.thing_istate = thing_istate;
exports.thing_ostate = thing_ostate;
exports.thing_meta = thing_meta;
exports.thing_model = thing_model;

exports.things = things;
<commit_msg>sort things<commit_after>/*
 *  things.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-01-08
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb.helpers;
var cfg = iotdb.cfg;

var mqtt = require('./mqtt');
var settings = require('./settings');
var helpers = require('./helpers');
var interactors = require('./interactors');

var bunyan = require('bunyan');
var logger = bunyan.createLogger({
    name: 'iotdb-runner',
    module: 'things',
});

/**
 *  Returns a Thing by thing_id
 */
var _get_thing = function(thing_id) {
    var iot = iotdb.iot();
    var things = iot.things()
    for (var ti = 0; ti < things.length; ti++) {
        var t = things[ti];
        if (t.thing_id() == thing_id) {
            return t
        }
    }

    console.log("# _get_thing: thing not found", thing_id)
    return null
}

var scrub_id = function(v) {
    if (!v) {
        return ""
    } else {
        return v.replace(/.*#/, '')
    }
}

var structured = {};

/**
 *  Clean up the structure. You can do this whenever
 *  you want - it will be rebuilt when need in
 *  _structure_thing. Specifically, you'll want to
 *  clear structures when the metadata changes.
 */
var _clear_structure = function(thing) {
    if (thing === undefined) {
        structured = {};
    } else {
        structured[thing.thing_id()] = undefined;
    }
}

/*
 *  Preprocess attributes
 *  - compact everything
 *  - find out if control or reading attibute
 */
var _structure_thing = function(thing) {
    var s = structured[thing.thing_id()];
    if (s) {
        return s;
    }

    var meta = thing.meta();
    var thing_name = meta.get('schema:name') || thing.name;

    /*
     *  Do initial pre-processing on attributes
     */
    var catd = {};
    var tats = thing.attributes()
    for (var tax in tats) {
        var tat = tats[tax]

        var cat = _.ld.compact(tat)
        cat._code = tat.get_code()

        var name = _.ld.first(cat, 'schema:name')
        cat['@id'] = "/api/things/" + thing.thing_id() + "/#" + cat._code;
        cat._name = name || cat._code;
        cat._thing_id = thing.thing_id();
        cat._thing_name = thing_name;
        cat._thing_group = thing_name + "@@" + thing.thing_id();
        cat._id = thing.thing_id() + "/#" + cat._code;
        cat.group = thing_name;

        var cid = scrub_id(_.ld.first(cat, "@id", ""))
        if (_.ld.list(cat, 'iot:role') === undefined) {
            cat._out = cid
            cat._in = cid
        }
        if (_.ld.contains(cat, 'iot:role', 'iot-attribute:role-control')) {
            cat._out = cid
        }
        if (_.ld.contains(cat, 'iot:role', 'iot-attribute:role-reading')) {
            cat._in = cid
        }

        catd[cid] = cat
    }

    /**
     *  Group related control/reading attributes together
     */
    for (var cid in catd) {
        var cat = catd[cid]
        if (cat._use === undefined) {
            cat._use = true
        }

        var rids = _.ld.list(cat, "iot:related-role", [])
        for (var rix in rids) {
            var rid = scrub_id(rids[rix])
            var rat = catd[rid]
            if (rat === undefined) {
                continue
            }

            if (rat._use === undefined) {
                rat._use = false
            }
            if (cat._out && !rat._out) {
                rat._out = cat._out
            }
            if (cat._in && !rat._in) {
                rat._in = cat._in
            }
        }

    }

    var cats = [];
    for (var ci in catd) {
        var cat = catd[ci];
        if (!cat._use) {
            continue;
        }

        cats.push(cat);
    }

    s = {
        thing_id: thing.thing_id(),
        cats: cats
    };
    structured[thing.thing_id()] = s;

    return s;
};

var structured = function() {
    var things = iotdb.iot().things();

    // order things by thing_name first
    var tts = [];
    for (var ti = 0; ti < things.length; ti++) {
        var thing = things[ti];
        var meta = thing.meta();
        var thing_name = meta.get('schema:name') || thing.name;
        if (thing_name === undefined) {
            continue
        }

        tts.push([ thing_name, thing ]);
    }

    tts.sort();

    // then get all the compressed attributes
    var cats = [];
    for (var ti in tts) {
        var tt = tts[ti];
        var thing = tt[1];
        var state = thing.state();
        var s = _structure_thing(thing);

        for (var ci in s.cats) {
            var cat = s.cats[ci];
            cat.state = state;

            cats.push(cat);
        }
    }

    return cats;
};

var _make_thing = function(f) {
    return function (request, response) {
        logger.info({
            method: "_make_thing",
            recipe_id: request.params.thing_id,
            body: request.body,
        }, "called");

        var thing = _get_thing(request.params.thing_id);
        if (!thing) {
            return response
                .set('Content-Type', 'application/json')
                .status(404)
                .send(JSON.stringify({
                    error: "thing not found",
                    thing_id: request.params.thing_id
                }, null, 2))
                ;
        }

        response.set('Content-Type', 'application/json');
        response.send(JSON.stringify(f(thing, request, response), null, 2));
    };
};

/**
 */
var thing_istate = function(thing) {
    return _.extend(
        thing.state({ istate: true, ostate: false }),
        {
            "@id": "/api/things/" + thing.thing_id() + "/istate",
        }
    );
};

/**
 */
var thing_ostate = function(thing) {
    return _.extend(
        thing.state({ istate: false, ostate: true }),
        {
            "@id": "/api/things/" + thing.thing_id() + "/ostate",
        }
    );
};

/**
 */
var thing_meta = function(thing) {
    return _.ld.compact(
        thing.meta().state(),
        {
            "@id": "/api/things/" + thing.thing_id() + "/meta",
        }
    );
};

/**
 */
var thing_model = function(thing) {
    var md = _.ld.compact(thing.jsonld({
        // base: "/api/things/" + thing.thing_id() + "/model",
    }));

    md["@context"] = {
        "iot": _.ld.namespace["iot"],
        "iot-unit": _.ld.namespace["iot-unit"],
        "iot-attribute": _.ld.namespace["iot-attribute"],
        "schema": _.ld.namespace["schema"],
    },
    md["@id"] = "/api/things/" + thing.thing_id() + "/model";

    var meta = thing.meta();
    md._id = thing.thing_id();
    md._name = meta.get("schema:name");

    var ads = _.ld.list(md, "iot:attribute", []);
    for (var adi in ads) {
        var ad = ads[adi];
        ad._code = ad["@id"].replace(/^.*#/, '');
        ad._control = false;
        ad._reading = false;
        ad._name = _.ld.first(ad, "schema:name");

        var roles = _.ld.list(ad, 'iot:role');
        if (!roles) {
            ad._control = true;
            ad._reading = true;
        } else {
            for (var ri in roles) {
                var role = roles[ri];
                if (role === 'iot-attribute:role-control') {
                    ad._control = true;
                } else if (role === 'iot-attribute:role-reading') {
                    ad._reading = true;
                }
            }
        }

        interactors.assign_interactor_to_attribute(ad);
    }

    return md;
};

/*
 */
var things = function() {
    var tds = [];
    var things = iotdb.iot().things();

    for (var ti = 0; ti < things.length; ti++) {
        var thing = things[ti];
        var td = {};
        var tmodel = thing_model(thing);

        td["_id"] = tmodel._id;
        td["_name"] = tmodel._name;
        td["_sort"] = tmodel._name + "@@" + tmodel._id;
        td["_section"] = "things";
        td["model"] = tmodel;
        td["istate"] = thing_istate(thing);
        td["ostate"] = thing_ostate(thing);
        td["meta"] = thing_meta(thing);

        tds.push(td);
    }

    tds.sort(function(a, b) {
        if (a._sort < b._sort) {
            return -1;
        } else if (a._sort > b._sort) {
            return 1
        } else {
            return 0;
        }
    });

    return tds;
};

/**
 *   get '/api/things/:thing_id/istate'
 */
var get_istate = _make_thing(thing_istate);

/**
 *   get '/api/things/:thing_id/ostate'
 */
var get_ostate = _make_thing(thing_ostate);

/**
 *   put '/api/things/:thing_id/ostate'
 */
var put_ostate = _make_thing(function(thing, request, response) {
    thing.update(request.body, { notify: true });

    return {};
});

/**
 *   get '/api/things/:thing_id/meta'
 */
var get_meta = _make_thing(thing_meta);

/**
 *   get '/api/things/:thing_id/model'
 */
var get_model = _make_thing(thing_model);

/**
 */
var setup = function() {
    var iot = iotdb.iot();
    var things = iot.connect();

    things.on_thing(function(thing) {
        thing.on("state", function(thing) {
            var topic = settings.d.mqttd.prefix + "api/things/" + thing.thing_id() + "/istate";
            var payload = thing_istate(thing);

            mqtt.publish(settings.d.mqttd, topic, payload);
        });
        thing.on("meta", function(thing) {
            var topic = settings.d.mqttd.prefix + "api/things/" + thing.thing_id() + "/meta";
            var payload = thing_meta(thing);

            mqtt.publish(settings.d.mqttd, topic, payload);

            // _clear_structure(thing);
            // someday publish a metadata change
        });
    });
};

/**
 *  API
 */
exports.setup = setup;

exports.get_istate = get_istate;
exports.get_ostate = get_ostate;
exports.put_ostate = put_ostate;
exports.get_meta = get_meta;
exports.get_model = get_model;

exports.thing_istate = thing_istate;
exports.thing_ostate = thing_ostate;
exports.thing_meta = thing_meta;
exports.thing_model = thing_model;

exports.things = things;
<|endoftext|>


<commit_before>namespace('Sy');

Sy.kernel = new Sy.Kernel.Core();
Sy.kernel.getConfig().set({
    env: 'prod',
    parameters: {
        app: {
            meta: {
                viewscreens: [] //array of objects containing `name` and `creator` attributes
            }
        },
        storage: {
            engines: [
                {
                    name: 'indexeddb',
                    factory: 'sy::core::storage::factory::engine::indexeddb',
                    mapper: 'sy::core::storage::storemapper::indexeddb'
                },
                {
                    name: 'localstorage',
                    factory: 'sy::core::storage::factory::engine::localstorage',
                    mapper: 'sy::core::storage::storemapper::localstorage'
                },
                {
                    name: 'rest',
                    factory: 'sy::core::storage::factory::engine::rest',
                    mapper: 'sy::core::storage::storemapper::rest'
                }
            ]
        }
    },
    controllers: {
        cache: true
    }
});

Sy.kernel.getServiceContainer()
    .setParameters(Sy.kernel.getConfig().get('parameters'))
    .set({
        'sy::core::generator::uuid': {
            constructor: 'Sy.Lib.Generator.UUID'
        },
        'sy::core::mediator': {
            constructor: 'Sy.Lib.Mediator',
            calls: [
                ['setGenerator', ['@sy::core::generator::uuid']],
                ['setLogger', ['@sy::core::logger']]
            ]
        },
        'sy::core::http::rest': {
            constructor: 'Sy.HTTP.REST',
            calls: [
                ['setManager', ['@sy::core::http']]
            ]
        },
        'sy::core::registry::factory': {
            constructor: 'Sy.RegistryFactory'
        },
        'sy::core::stateregistry::factory': {
            constructor: 'Sy.StateRegistryFactory',
            calls: [
                ['setRegistryFactory', ['@sy::core::registry::factory']]
            ]
        },
        'sy::core::view::parser': {
            constructor: 'Sy.View.Parser'
        },
        'sy::core::view::factory::list': {
            constructor: 'Sy.View.ListFactory',
            calls: [
                ['setTemplateEngine', ['@sy::core::view::template::engine']]
            ]
        },
        'sy::core::view::factory::layout': {
            constructor: 'Sy.View.LayoutFactory',
            calls: [
                ['setParser', ['@sy::core::view::parser']],
                ['setTemplateEngine', ['@sy::core::view::template::engine']],
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setListFactory', ['@sy::core::view::factory::list']]
            ]
        },
        'sy::core::view::factory::viewscreen': {
            constructor: 'Sy.View.ViewScreenFactory',
            calls: [
                ['setParser', ['@sy::core::view::parser']],
                ['setTemplateEngine', ['@sy::core::view::template::engine']],
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setLayoutFactory', ['@sy::core::view::factory::layout']],
                ['setDefinedWrappers', ['%app.meta.viewscreens%']]
            ]
        },
        'sy::core::storage::factory::engine::indexeddb': {
            constructor: 'Sy.Storage.EngineFactory.IndexedDBFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']]
            ]
        },
        'sy::core::storage::factory::engine::localstorage': {
            constructor: 'Sy.Storage.EngineFactory.LocalstorageFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']]
            ]
        },
        'sy::core::storage::factory::engine::rest': {
            constructor: 'Sy.Storage.EngineFactory.RestFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']],
                ['setManager', ['@sy::core::http::rest']]
            ]
        },
        'sy::core::storage::storemapper::indexeddb': {
            constructor: 'Sy.Storage.StoreMapper.IndexedDBMapper'
        },
        'sy::core::storage::storemapper::localstorage': {
            constructor: 'Sy.Storage.StoreMapper.LocalstorageMapper'
        },
        'sy::core::storage::storemapper::rest': {
            constructor: 'Sy.Storage.StoreMapper.RestMapper'
        },
        'sy::core::storage::unitofwork::factory': {
            constructor: 'Sy.Storage.UnitOfWorkFactory',
            calls: [
                ['setGenerator', ['@sy::core::generator::uuid']],
                ['setStateRegistryFactory', ['@sy::core::stateregistry::factory']]
            ]
        },
        'sy::core::storage::repository::factory': {
            constructor: 'Sy.Storage.RepositoryFactory',
            calls: [
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setUOWFactory', ['@sy::core::storage::unitofwork::factory']],
                ['setMeta', ['%app.meta.entities%']]
            ]
        }
    })
    .set('sy::core::logger', function () {

        var logger = new Sy.Lib.Logger.CoreLogger('core'),
            info = new Sy.Lib.Logger.Handler.Console(logger.INFO),
            debug = new Sy.Lib.Logger.Handler.Console(logger.DEBUG),
            error = new Sy.Lib.Logger.Handler.Console(logger.ERROR),
            log = new Sy.Lib.Logger.Handler.Console(logger.LOG);

        logger.setHandler(info, logger.INFO);
        logger.setHandler(debug, logger.DEBUG);
        logger.setHandler(error, logger.ERROR);
        logger.setHandler(log, logger.LOG);

        return logger;

    })
    .set('sy::core::http', function () {

        var parser = new Sy.HTTP.HeaderParser(),
            manager = new Sy.HTTP.Manager();

        manager.setParser(parser);
        manager.setGenerator(this.get('sy::core::generator::uuid'));
        manager.setRegistry(this.get('sy::core::registry::factory').make());
        manager.setLogger(this.get('sy::core::logger'));

        return manager;
    })
    .set('sy::core::storage::factory::engine::core', function () {

        var factory = new Sy.Storage.EngineFactory.Core(),
            factories = this.getParameter('storage.engines');

        factory.setRegistry(
            this.get('sy::core::registry::factory').make()
        );

        for (var i = 0, l = factories.length; i < l; i++) {
            factory.setEngineFactory(
                factories[i].name,
                this.get(factories[i].factory),
                this.get(factories[i].mapper)
            );
        }

        return factory;

    })
    .set('sy::core::storage', function () {

        var meta = this.getParameter('app.meta.entities'),
            storage = new Sy.Storage.Core(),
            managerFact = new Sy.Storage.ManagerFactory(),
            engineFact = this.get('sy::core::storage::factory::engine::core'),
            conf = this.getParameter('storage.managers'),
            registryFact = this.get('sy::core::registry::factory');

        storage.setRegistry(registryFact.make());

        managerFact
            .setEngineFactory(engineFact)
            .setRepositoryFactory(this.get('sy::core::storage::repository::factory'));

        for (var name in conf) {
            if (conf.hasOwnProperty(name)) {
                var manager = managerFact.make(name, conf[name], meta);

                storage.setManager(name, manager);
            }
        }

        return storage;

    })
    .set('sy::core::translator', function () {
        var translator = new Sy.Translator();
        translator
            .setRegistry(this.get('sy::core::registry::factory').make())
            .setStateRegistryFactory(this.get('sy::core::stateregistry::factory'));
        return translator;
    })
    .set('sy::core::view::template::engine', function () {
        var engine = new Sy.View.TemplateEngine();

        return engine
            .setRegistry(
                this.get('sy::core::registry::factory').make()
            )
            .setGenerator(
                this.get('sy::core::generator::uuid')
            );
    })
    .set('sy::core::viewport', function () {

        var viewport = new Sy.View.ViewPort();

        return viewport
            .setNode(
                document.querySelector('.viewport')
            )
            .setViewManager(
                this.get('sy::core::view::manager')
            )
            .setMediator(
                this.get('sy::core::mediator')
            );

    })
    .set('sy::core::view::manager', function () {

        var manager = new Sy.View.Manager(),
            viewscreens = this.get('sy::core::view::parser').getViewScreens();

        manager
            .setViewsRegistry(
                this.get('sy::core::registry::factory').make()
            )
            .setViewScreenFactory(
                this.get('sy::core::view::factory::viewscreen')
            );

        for (var i = 0, l = viewscreens.length; i < l; i++) {
            manager.setViewScreen(viewscreens[i]);

            if (!DOM(viewscreens[i]).isChildOf('.viewport')){
                viewscreens[i].parentNode.removeChild(viewscreens[i]);
            }
        }

        return manager;

    })
    .set('sy::core::validator', function () {
        var validator = new Sy.Validator.Core(),
            contextFactory = new Sy.Validator.ExecutionContextFactory();

        contextFactory.setConstraintValidatorFactory(new Sy.Validator.ConstraintValidatorFactory());

        return validator
            .setRulesRegistry(this.get('sy::core::registry::factory').make())
            .setContextFactory(contextFactory)
            .setConstraintFactory(new Sy.Validator.ConstraintFactory());
    });
<commit_msg>made form builder available via a service<commit_after>namespace('Sy');

Sy.kernel = new Sy.Kernel.Core();
Sy.kernel.getConfig().set({
    env: 'prod',
    parameters: {
        app: {
            meta: {
                viewscreens: [] //array of objects containing `name` and `creator` attributes
            }
        },
        storage: {
            engines: [
                {
                    name: 'indexeddb',
                    factory: 'sy::core::storage::factory::engine::indexeddb',
                    mapper: 'sy::core::storage::storemapper::indexeddb'
                },
                {
                    name: 'localstorage',
                    factory: 'sy::core::storage::factory::engine::localstorage',
                    mapper: 'sy::core::storage::storemapper::localstorage'
                },
                {
                    name: 'rest',
                    factory: 'sy::core::storage::factory::engine::rest',
                    mapper: 'sy::core::storage::storemapper::rest'
                }
            ]
        }
    },
    controllers: {
        cache: true
    }
});

Sy.kernel.getServiceContainer()
    .setParameters(Sy.kernel.getConfig().get('parameters'))
    .set({
        'sy::core::generator::uuid': {
            constructor: 'Sy.Lib.Generator.UUID'
        },
        'sy::core::mediator': {
            constructor: 'Sy.Lib.Mediator',
            calls: [
                ['setGenerator', ['@sy::core::generator::uuid']],
                ['setLogger', ['@sy::core::logger']]
            ]
        },
        'sy::core::http::rest': {
            constructor: 'Sy.HTTP.REST',
            calls: [
                ['setManager', ['@sy::core::http']]
            ]
        },
        'sy::core::registry::factory': {
            constructor: 'Sy.RegistryFactory'
        },
        'sy::core::stateregistry::factory': {
            constructor: 'Sy.StateRegistryFactory',
            calls: [
                ['setRegistryFactory', ['@sy::core::registry::factory']]
            ]
        },
        'sy::core::view::parser': {
            constructor: 'Sy.View.Parser'
        },
        'sy::core::view::factory::list': {
            constructor: 'Sy.View.ListFactory',
            calls: [
                ['setTemplateEngine', ['@sy::core::view::template::engine']]
            ]
        },
        'sy::core::view::factory::layout': {
            constructor: 'Sy.View.LayoutFactory',
            calls: [
                ['setParser', ['@sy::core::view::parser']],
                ['setTemplateEngine', ['@sy::core::view::template::engine']],
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setListFactory', ['@sy::core::view::factory::list']]
            ]
        },
        'sy::core::view::factory::viewscreen': {
            constructor: 'Sy.View.ViewScreenFactory',
            calls: [
                ['setParser', ['@sy::core::view::parser']],
                ['setTemplateEngine', ['@sy::core::view::template::engine']],
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setLayoutFactory', ['@sy::core::view::factory::layout']],
                ['setDefinedWrappers', ['%app.meta.viewscreens%']]
            ]
        },
        'sy::core::storage::factory::engine::indexeddb': {
            constructor: 'Sy.Storage.EngineFactory.IndexedDBFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']]
            ]
        },
        'sy::core::storage::factory::engine::localstorage': {
            constructor: 'Sy.Storage.EngineFactory.LocalstorageFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']]
            ]
        },
        'sy::core::storage::factory::engine::rest': {
            constructor: 'Sy.Storage.EngineFactory.RestFactory',
            calls: [
                ['setLogger', ['@sy::core::logger']],
                ['setMediator', ['@sy::core::mediator']],
                ['setManager', ['@sy::core::http::rest']]
            ]
        },
        'sy::core::storage::storemapper::indexeddb': {
            constructor: 'Sy.Storage.StoreMapper.IndexedDBMapper'
        },
        'sy::core::storage::storemapper::localstorage': {
            constructor: 'Sy.Storage.StoreMapper.LocalstorageMapper'
        },
        'sy::core::storage::storemapper::rest': {
            constructor: 'Sy.Storage.StoreMapper.RestMapper'
        },
        'sy::core::storage::unitofwork::factory': {
            constructor: 'Sy.Storage.UnitOfWorkFactory',
            calls: [
                ['setGenerator', ['@sy::core::generator::uuid']],
                ['setStateRegistryFactory', ['@sy::core::stateregistry::factory']]
            ]
        },
        'sy::core::storage::repository::factory': {
            constructor: 'Sy.Storage.RepositoryFactory',
            calls: [
                ['setRegistryFactory', ['@sy::core::registry::factory']],
                ['setUOWFactory', ['@sy::core::storage::unitofwork::factory']],
                ['setMeta', ['%app.meta.entities%']]
            ]
        },
        'sy::core::form': {
            constructor: 'Sy.Form.Builder',
            calls: [
                ['setValidator', ['@sy::core::validator']]
            ]
        }
    })
    .set('sy::core::logger', function () {

        var logger = new Sy.Lib.Logger.CoreLogger('core'),
            info = new Sy.Lib.Logger.Handler.Console(logger.INFO),
            debug = new Sy.Lib.Logger.Handler.Console(logger.DEBUG),
            error = new Sy.Lib.Logger.Handler.Console(logger.ERROR),
            log = new Sy.Lib.Logger.Handler.Console(logger.LOG);

        logger.setHandler(info, logger.INFO);
        logger.setHandler(debug, logger.DEBUG);
        logger.setHandler(error, logger.ERROR);
        logger.setHandler(log, logger.LOG);

        return logger;

    })
    .set('sy::core::http', function () {

        var parser = new Sy.HTTP.HeaderParser(),
            manager = new Sy.HTTP.Manager();

        manager.setParser(parser);
        manager.setGenerator(this.get('sy::core::generator::uuid'));
        manager.setRegistry(this.get('sy::core::registry::factory').make());
        manager.setLogger(this.get('sy::core::logger'));

        return manager;
    })
    .set('sy::core::storage::factory::engine::core', function () {

        var factory = new Sy.Storage.EngineFactory.Core(),
            factories = this.getParameter('storage.engines');

        factory.setRegistry(
            this.get('sy::core::registry::factory').make()
        );

        for (var i = 0, l = factories.length; i < l; i++) {
            factory.setEngineFactory(
                factories[i].name,
                this.get(factories[i].factory),
                this.get(factories[i].mapper)
            );
        }

        return factory;

    })
    .set('sy::core::storage', function () {

        var meta = this.getParameter('app.meta.entities'),
            storage = new Sy.Storage.Core(),
            managerFact = new Sy.Storage.ManagerFactory(),
            engineFact = this.get('sy::core::storage::factory::engine::core'),
            conf = this.getParameter('storage.managers'),
            registryFact = this.get('sy::core::registry::factory');

        storage.setRegistry(registryFact.make());

        managerFact
            .setEngineFactory(engineFact)
            .setRepositoryFactory(this.get('sy::core::storage::repository::factory'));

        for (var name in conf) {
            if (conf.hasOwnProperty(name)) {
                var manager = managerFact.make(name, conf[name], meta);

                storage.setManager(name, manager);
            }
        }

        return storage;

    })
    .set('sy::core::translator', function () {
        var translator = new Sy.Translator();
        translator
            .setRegistry(this.get('sy::core::registry::factory').make())
            .setStateRegistryFactory(this.get('sy::core::stateregistry::factory'));
        return translator;
    })
    .set('sy::core::view::template::engine', function () {
        var engine = new Sy.View.TemplateEngine();

        return engine
            .setRegistry(
                this.get('sy::core::registry::factory').make()
            )
            .setGenerator(
                this.get('sy::core::generator::uuid')
            );
    })
    .set('sy::core::viewport', function () {

        var viewport = new Sy.View.ViewPort();

        return viewport
            .setNode(
                document.querySelector('.viewport')
            )
            .setViewManager(
                this.get('sy::core::view::manager')
            )
            .setMediator(
                this.get('sy::core::mediator')
            );

    })
    .set('sy::core::view::manager', function () {

        var manager = new Sy.View.Manager(),
            viewscreens = this.get('sy::core::view::parser').getViewScreens();

        manager
            .setViewsRegistry(
                this.get('sy::core::registry::factory').make()
            )
            .setViewScreenFactory(
                this.get('sy::core::view::factory::viewscreen')
            );

        for (var i = 0, l = viewscreens.length; i < l; i++) {
            manager.setViewScreen(viewscreens[i]);

            if (!DOM(viewscreens[i]).isChildOf('.viewport')){
                viewscreens[i].parentNode.removeChild(viewscreens[i]);
            }
        }

        return manager;

    })
    .set('sy::core::validator', function () {
        var validator = new Sy.Validator.Core(),
            contextFactory = new Sy.Validator.ExecutionContextFactory();

        contextFactory.setConstraintValidatorFactory(new Sy.Validator.ConstraintValidatorFactory());

        return validator
            .setRulesRegistry(this.get('sy::core::registry::factory').make())
            .setContextFactory(contextFactory)
            .setConstraintFactory(new Sy.Validator.ConstraintFactory());
    });
<|endoftext|>


<commit_before>/*
===============================================================================================

		Unify Project

		Homepage: unify-project.org
		License: MIT + Apache (V2)
		Copyright: 2012, Sebastian Fastner, Mainz, Germany, http://unify-training.com

===============================================================================================
*/

/**
 * Detects the operating system name
 */
core.Module("unify.bom.detect.Develop", {

	/** {=Boolean} True is source variant */
	VALUE : (function(location) {
		return location.pathname.contains("/source/");
	})(this.location)
});<commit_msg>Fix use of not available Array.contains in some cases in detection<commit_after>/*
===============================================================================================

		Unify Project

		Homepage: unify-project.org
		License: MIT + Apache (V2)
		Copyright: 2012, Sebastian Fastner, Mainz, Germany, http://unify-training.com

===============================================================================================
*/

/**
 * Detects the operating system name
 */
core.Module("unify.bom.detect.Develop", {

	/** {=Boolean} True is source variant */
	VALUE : (function(location) {
		return location.pathname.indexOf("/source/") !== -1;
	})(this.location)
});
<|endoftext|>