<commit_before>/*-
 * Copyright (c) 2016 Red Hat, Inc.
 *
 * 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.
 */

function loadDependencyGraph(data) {
    var s = '';
    for ( var pkg in data) {
        if (data.hasOwnProperty(pkg)) {
            s += '"' + pkg + '";';
            deps = data[pkg];
            deps.forEach(function(dep) {
                s += '"' + pkg + '" -> "' + dep + '";';
            });
        }
    }
    $("#jsviz").html(Viz('digraph {' + s + '}'));
}

function createDependencyGraphDiff(data1, data2) {
    var s = '';

    var data = {};

    for ( var pkg in data1) {
        if (data1.hasOwnProperty(pkg)) {
            data[pkg] = data1[pkg];
        }
    }
    for ( var pkg in data2) {
        if (data2.hasOwnProperty(pkg)) {
            if (data.hasOwnProperty(pkg)) {
                var merged = data[pkg].concat(data2[pkg]).sort();
                data[pkg] = merged.filter(function(item, pos) {
                    return merged.indexOf(item) == pos
                })
            } else {
                data[pkg] = data2[pkg];
            }
        }
    }

    for ( var pkg in data) {
        if (data.hasOwnProperty(pkg)) {
            s += '"' + pkg + '"';
            if (!data1.hasOwnProperty(pkg)) {
                s += "[color=green;fontcolor=green]";
            } else if (!data2.hasOwnProperty(pkg)) {
                s += "[color=red;fontcolor=red]";
            }
            s += ";";
            deps = data[pkg];
            deps.forEach(function(dep) {
                s += '"' + pkg + '" -> "' + dep + '"';
                if (!data1.hasOwnProperty(pkg) || !data1.hasOwnProperty(dep)
                        || data1[pkg].indexOf(dep) == -1) {
                    s += "[color=green]";
                } else if (!data2.hasOwnProperty(pkg)
                        || !data2.hasOwnProperty(dep)
                        || data2[pkg].indexOf(dep) == -1) {
                    s += "[color=red]";
                }
                s += ";";
            });
        }
    }
    $("#jsviz").html(Viz('digraph {' + s + '}'));
}

function loadDependencyGraphDiff(oldId, newId) {
    $.getJSON("api/data/graph/" + oldId, function(oldData) {
        $.getJSON("api/data/graph/" + newId, function(newData) {
            createDependencyGraphDiff(oldData, newData);
        });
    });
}
<commit_msg>Add tooltips to dependency graphs<commit_after>/*-
 * Copyright (c) 2016 Red Hat, Inc.
 *
 * 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.
 */

function loadDependencyGraph(data) {
    var s = '';
    for ( var pkg in data) {
        if (data.hasOwnProperty(pkg)) {
            s += '"' + pkg + '"[tooltip="' + pkg + '"];';
            deps = data[pkg];
            deps.forEach(function(dep) {
                s += '"' + pkg + '" -> "' + dep + '"';
                s += '[tooltip="' + pkg + ' requires ' + dep + '"];';
            });
        }
    }
    $("#jsviz").html(Viz('digraph {' + s + '}'));
}

function createDependencyGraphDiff(data1, data2) {
    var s = '';

    var data = {};

    for ( var pkg in data1) {
        if (data1.hasOwnProperty(pkg)) {
            data[pkg] = data1[pkg];
        }
    }
    for ( var pkg in data2) {
        if (data2.hasOwnProperty(pkg)) {
            if (data.hasOwnProperty(pkg)) {
                var merged = data[pkg].concat(data2[pkg]).sort();
                data[pkg] = merged.filter(function(item, pos) {
                    return merged.indexOf(item) == pos
                })
            } else {
                data[pkg] = data2[pkg];
            }
        }
    }

    for ( var pkg in data) {
        if (data.hasOwnProperty(pkg)) {
            s += '"' + pkg + '"[';
            if (!data1.hasOwnProperty(pkg)) {
                s += 'color=green;fontcolor=green;';
            } else if (!data2.hasOwnProperty(pkg)) {
                s += 'color=red;fontcolor=red;';
            }
            s += 'tooltip="' + pkg + '"];';
            deps = data[pkg];
            deps.forEach(function(dep) {
                s += '"' + pkg + '" -> "' + dep + '"[';
                if (!data1.hasOwnProperty(pkg) || !data1.hasOwnProperty(dep)
                        || data1[pkg].indexOf(dep) == -1) {
                    s += 'color=green;';
                } else if (!data2.hasOwnProperty(pkg)
                        || !data2.hasOwnProperty(dep)
                        || data2[pkg].indexOf(dep) == -1) {
                    s += 'color=red;';
                }
                s += 'tooltip="' + pkg + ' requires ' + dep + '"];';
            });
        }
    }
    $("#jsviz").html(Viz('digraph {' + s + '}'));
}

function loadDependencyGraphDiff(oldId, newId) {
    $.getJSON("api/data/graph/" + oldId, function(oldData) {
        $.getJSON("api/data/graph/" + newId, function(newData) {
            createDependencyGraphDiff(oldData, newData);
        });
    });
}
<|endoftext|>


<commit_before>define(["app", "backbone", "places/models/POIModel", "places/views/CategoriesView", "places/views/SearchView", "places/views/MapView", "places/views/DetailView", "places/collections/POICollection", "hbs!places/templates/list-map-layout", "backbone.subroute"], function(app, Backbone, POI, CategoriesView, SearchView, MapView, DetailView, POIs, ListMapTemplate){

    var pois = new POIs();
    var PlacesRouter = Backbone.SubRoute.extend({

        // All of your Backbone Routes (add more)
        routes: {

            "": "categories",
            "categories": "categories",
            "categories/*category_name": "categories",
            "search": "search",
            ":id": "detail"

        },

        categories: function(category_name) {
            // Navigate to the list of categories (root view of places)
            categoriesView = new CategoriesView({category_name: category_name});
            app.showView(categoriesView);
        },

        search: function(params) {
            mapView = new MapView({
                collection: pois
            });
            searchView = new SearchView({
                collection: pois,
                params: params
            });
            var layout = new Backbone.Layout({
                template: ListMapTemplate,
                views: {
                    ".content-detail": mapView,
                    "#list": searchView
                }
            });
            app.showView(layout, {back: true});
            mapView.invalidateMapSize();
        },

        detail: function(id, params) {
            detailView = new DetailView({
                model: POI,
                params: params,
                poid: id
            });
            app.showView(detailView);
            detailView.invalidateMapSize();
        }

    });

    // Returns the Router class
    return PlacesRouter;

});
<commit_msg>Listen for selected POIs and render details<commit_after>define(["app", "backbone", "places/models/POIModel", "places/views/CategoriesView", "places/views/SearchView", "places/views/MapView", "places/views/DetailView", "places/collections/POICollection", "hbs!places/templates/list-map-layout", "backbone.subroute"], function(app, Backbone, POI, CategoriesView, SearchView, MapView, DetailView, POIs, ListMapTemplate){

    var pois = new POIs();
    var PlacesRouter = Backbone.SubRoute.extend({

        // All of your Backbone Routes (add more)
        routes: {

            "": "categories",
            "categories": "categories",
            "categories/*category_name": "categories",
            "search": "search",
            ":id": "detail"

        },

        categories: function(category_name) {
            // Navigate to the list of categories (root view of places)
            categoriesView = new CategoriesView({category_name: category_name});
            app.showView(categoriesView);
        },

        search: function(params) {
            mapView = new MapView({
                collection: pois
            });
            searchView = new SearchView({
                collection: pois,
                params: params
            });
            var layout = new Backbone.Layout({
                template: ListMapTemplate,
                views: {
                    ".content-detail": mapView,
                    "#list": searchView
                },
                afterRender: function() {
                    that = this;
                    pois.on("change:selected", function(poi) {
                        that.setView("#list", new DetailView({model: poi})).render();
                    });
                }
            });
            app.showView(layout, {back: true});
            mapView.invalidateMapSize();
        },

        detail: function(id, params) {
            detailView = new DetailView({
                model: POI,
                params: params,
                poid: id
            });
            app.showView(detailView);
            detailView.invalidateMapSize();
        }

    });

    // Returns the Router class
    return PlacesRouter;

});
<|endoftext|>


<commit_before><commit_msg>Basic route handling for bills.<commit_after>/**
 * Main application container for the Legislature Tracker
 */
var LTApplication = Backbone.Router.extend({
  routes: {
    'bill/:bill': 'bill',
    '*default': 'default'
  },

  initialize: function(options) {
    this.options = options;
    // Data cache is used to store loaded models
    // as this data does not change that often
    this.dataCache = {};

    Backbone.history.start();
  },

  default: function() {

  },

  // Bill page
  bill: function(bill) {
    this.loadModel('OSBillModel', 'bill_id', bill, function(bill, data, xhr) {

    });
  },

  // General load model method to use cache.
  loadModel: function(type, idAttr, id, callback) {
    var attrs = {};
    this.dataCache[type] = this.dataCache[type] || {};

    if (_.isUndefined(this.dataCache[type][id])) {
      attrs[idAttr] = id;
      this.dataCache[type][id] = new window[type](
        attrs, this.options);
      this.dataCache[type][id].fetch({
        success: callback,
        error: this.error
      });
    }
    else {
      callback.apply(this, [ this.dataCache[type][id], false ]);
    }
  },

  error: function(e) {
    // Handle error
  }
});<|endoftext|>


<commit_before>import bip39 from 'bip39'
import { encrypt, decrypt, decryptPrivateKeychain, getIdentityPrivateKeychain, getBitcoinPrivateKeychain } from '../utils'
import { PrivateKeychain, PublicKeychain, getEntropy } from 'blockstack-keychains'
import { ECPair } from 'bitcoinjs-lib'
import { authorizationHeaderValue } from '../utils'

const CREATE_ACCOUNT = 'CREATE_ACCOUNT',
      DELETE_ACCOUNT = 'DELETE_ACCOUNT',
      NEW_IDENTITY_ADDRESS = 'NEW_IDENTITY_ADDRESS',
      NEW_BITCOIN_ADDRESS = 'NEW_BITCOIN_ADDRESS',
      UPDATE_BACKUP_PHRASE = 'UPDATE_BACKUP_PHRASE',
      UPDATE_BALANCES = 'UPDATE_BALANCES',
      UPDATE_CORE_ADDRESS = 'UPDATE_CORE_ADDRESS',
      UPDATE_CORE_BALANCE = 'UPDATE_CORE_BALANCE'

function createAccount(encryptedBackupPhrase, privateKeychain, email=null) {
  const identityPrivateKeychain = getIdentityPrivateKeychain(privateKeychain)
  const bitcoinPrivateKeychain = getBitcoinPrivateKeychain(privateKeychain)

  const identityPublicKeychain = identityPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')
  const bitcoinPublicKeychain = bitcoinPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')
  const firstIdentityAddress = identityPrivateKeychain.ecPair.getAddress()
  const firstBitcoinAddress = bitcoinPrivateKeychain.ecPair.getAddress()

  const firstIdentityKey = identityPrivateKeychain.ecPair.d.toBuffer(32).toString('hex')
  const firstIdentityKeyID = identityPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')

  let analyticsId = identityPublicKeychain
  if (email) {
    analyticsId = email
  }
  mixpanel.track('Create account', { distinct_id: analyticsId })
  mixpanel.track('Perform action', { distinct_id: analyticsId })

  return {
    type: CREATE_ACCOUNT,
    encryptedBackupPhrase: encryptedBackupPhrase,
    identityPublicKeychain: identityPublicKeychain,
    bitcoinPublicKeychain: bitcoinPublicKeychain,
    firstIdentityAddress: firstIdentityAddress,
    firstBitcoinAddress: firstBitcoinAddress,
    firstIdentityKey: firstIdentityKey,
    firstIdentityKeyID: firstIdentityKeyID,
    analyticsId: analyticsId
  }
}

function updateCoreWalletAddress(coreWalletAddress) {
  return {
    type: UPDATE_CORE_ADDRESS,
    coreWalletAddress: coreWalletAddress
  }
}

function updateCoreWalletBalance(coreWalletBalance) {
  return {
    type: UPDATE_CORE_BALANCE,
    coreWalletBalance: coreWalletBalance
  }
}

function deleteAccount() {
  return {
    type: DELETE_ACCOUNT,
    encryptedBackupPhrase: null,
    accountCreated: false
  }
}

function updateBackupPhrase(encryptedBackupPhrase) {
  return {
    type: UPDATE_BACKUP_PHRASE,
    encryptedBackupPhrase: encryptedBackupPhrase
  }
}

function updateBalances(balances) {
  return {
    type: UPDATE_BALANCES,
    balances: balances
  }
}

function refreshCoreWalletBalance(addressBalanceUrl, coreWalletAddress) {
  return dispatch => {
    const url = addressBalanceUrl.replace('{address}', coreWalletAddress)
    fetch(url)
    .then((response) => response.text())
    .then((responseText) => JSON.parse(responseText))
    .then((responseJson) => {
      console.log(responseJson)
      const balance = responseJson.unconfirmedBalance + responseJson.balance
      console.log(balance)
      dispatch(
        updateCoreWalletBalance(balance)
      )
    })
  }
}

function getCoreWalletAddress(walletPaymentAddressUrl) {
  return dispatch => {
    const headers = {"Authorization": authorizationHeaderValue() }
    fetch(walletPaymentAddressUrl, { headers: headers })
    .then((response) => response.text())
    .then((responseText) => JSON.parse(responseText))
    .then((responseJson) => {
      const address = responseJson.address
      dispatch(
        updateCoreWalletAddress(address)
      )
    })
  }
}

function refreshBalances(addressBalanceUrl, addresses) {
  return dispatch => {
    let results = []
    addresses.forEach((address) => {

      // fetch balances from https://explorer.blockstack.org/insight-api/addr/{address}/?noTxList=1
      // parse results from: {"addrStr":"1Fvoya7XMvzfpioQnzaskndL7YigwHDnRE","balance":0.02431567,"balanceSat":2431567,"totalReceived":38.82799913,"totalReceivedSat":3882799913,"totalSent":38.80368346,"totalSentSat":3880368346,"unconfirmedBalance":0,"unconfirmedBalanceSat":0,"unconfirmedTxApperances":0,"txApperances":2181}
      const url = addressBalanceUrl.replace('{address}', address)
      fetch(url).then((response) => response.text())
      .then((responseText) => JSON.parse(responseText))
      .then((responseJson) => {

        results.push({
          address: address,
          balance: responseJson['balance']
        })

        if(results.length >= addresses.length) {
          let balances = {}
          let total = 0.0

          for(let i = 0; i < results.length; i++) {
            let address = results[i]['address']
            if(!balances.hasOwnProperty(address)) {
              let balance = results[i]['balance']
              total = total + balance
              balances[address] = balance
            } else {
              console.warn(`Duplicate address ${address} in addresses array`)
            }

          }

          balances['total'] = total

          dispatch(
            updateBalances(balances)
          )
        }
      })
    })
  }
}

function initializeWallet(password, backupPhrase, email=null) {
  return dispatch => {
    let privateKeychain
    if (backupPhrase && bip39.validateMnemonic(backupPhrase)) {
      privateKeychain = PrivateKeychain.fromMnemonic(backupPhrase)
    } else {
      privateKeychain = new PrivateKeychain()
      backupPhrase = privateKeychain.mnemonic()
    }

    encrypt(new Buffer(backupPhrase), password, function(err, ciphertextBuffer) {
      const encryptedBackupPhrase = ciphertextBuffer.toString('hex')
      dispatch(
        createAccount(encryptedBackupPhrase, privateKeychain, email)
      )
    })
  }
}

function newIdentityAddress() {
  return {
    type: NEW_IDENTITY_ADDRESS
  }
}

function newBitcoinAddress() {
  return {
    type: NEW_BITCOIN_ADDRESS
  }
}

export const AccountActions = {
  createAccount: createAccount,
  updateBackupPhrase: updateBackupPhrase,
  initializeWallet: initializeWallet,
  newIdentityAddress: newIdentityAddress,
  newBitcoinAddress: newBitcoinAddress,
  deleteAccount: deleteAccount,
  refreshBalances: refreshBalances,
  getCoreWalletAddress: getCoreWalletAddress,
  refreshCoreWalletBalance: refreshCoreWalletBalance
}

const initialState = {
  accountCreated: false,
  encryptedBackupPhrase: null,
  identityAccount: {
    addresses: [],
    keypairs: []
  },
  bitcoinAccount: {
    addresses: [],
    balances: { total: 0.0 }
  },
  analyticsId: '',
  coreWalletAddress: null,
  coreWalletBalance: 0.0
}

export function AccountReducer(state=initialState, action) {
  switch (action.type) {
    case CREATE_ACCOUNT:
      return Object.assign({}, state, {
        accountCreated: true,
        encryptedBackupPhrase: action.encryptedBackupPhrase,
        identityAccount: {
          publicKeychain: action.identityPublicKeychain,
          addresses: [
            action.firstIdentityAddress
          ],
          keypairs: [
            { key: action.firstIdentityKey,
              keyID: action.firstIdentityKeyID,
              address: action.firstIdentityAddress }
          ],
          addressIndex: 0
        },
        bitcoinAccount: {
          publicKeychain: action.bitcoinPublicKeychain,
          addresses: [
            action.firstBitcoinAddress
          ],
          addressIndex: 0,
          balances: state.bitcoinAccount.balances
        },
        analyticsId: action.analyticsId
      })
    case DELETE_ACCOUNT:
      return Object.assign({}, state, {
        accountCreated: false,
        encryptedBackupPhrase: null
      })
    case UPDATE_CORE_ADDRESS:
      return Object.assign({}, state, {
        coreWalletAddress: action.coreWalletAddress
      })
    case UPDATE_CORE_BALANCE:
      return Object.assign({}, state, {
        coreWalletBalance: action.coreWalletBalance
      })
    case UPDATE_BACKUP_PHRASE:
      return Object.assign({}, state, {
        encryptedBackupPhrase: action.encryptedBackupPhrase
      })
    case NEW_IDENTITY_ADDRESS:
      return Object.assign({}, state, {
        identityAccount: {
          publicKeychain: state.identityAccount.publicKeychain,
          addresses: [
            ...state.identityAccount.addresses,
            new PublicKeychain(state.identityAccount.publicKeychain)
              .publiclyEnumeratedChild(state.identityAccount.addressIndex + 1)
              .address().toString()
          ],
          addressIndex: state.identityAccount.addressIndex + 1
        }
      })
    case NEW_BITCOIN_ADDRESS:
      return Object.assign({}, state, {
        bitcoinAccount: {
          publicKeychain: state.bitcoinAccount.publicKeychain,
          addresses: [
            ...state.bitcoinAccount.addresses,
            new PublicKeychain(state.bitcoinAccount.publicKeychain)
              .publiclyEnumeratedChild(state.bitcoinAccount.addressIndex + 1)
              .address().toString()
          ],
          addressIndex: state.bitcoinAccount.addressIndex + 1,
          balances: state.bitcoinAccount.balances
        }
      })
    case UPDATE_BALANCES:
    return Object.assign({}, state, {
      bitcoinAccount: {
        publicKeychain: state.bitcoinAccount.publicKeychain,
        addresses: state.bitcoinAccount.addresses,
        balances: action.balances
      }
    })
    default:
      return state
  }
}
<commit_msg>add AuthActions and the requisite reducer steps to set the core session token state<commit_after>import bip39 from 'bip39'
import { encrypt, decrypt, decryptPrivateKeychain, getIdentityPrivateKeychain, getBitcoinPrivateKeychain } from '../utils'
import { PrivateKeychain, PublicKeychain, getEntropy } from 'blockstack-keychains'
import { ECPair } from 'bitcoinjs-lib'
import { authorizationHeaderValue, CORE_API_PASSWORD } from '../utils'
import { getCoreSession } from 'blockstack'
const CREATE_ACCOUNT = 'CREATE_ACCOUNT',
      DELETE_ACCOUNT = 'DELETE_ACCOUNT',
      NEW_IDENTITY_ADDRESS = 'NEW_IDENTITY_ADDRESS',
      NEW_BITCOIN_ADDRESS = 'NEW_BITCOIN_ADDRESS',
      UPDATE_BACKUP_PHRASE = 'UPDATE_BACKUP_PHRASE',
      UPDATE_BALANCES = 'UPDATE_BALANCES',
      UPDATE_CORE_ADDRESS = 'UPDATE_CORE_ADDRESS',
      UPDATE_CORE_BALANCE = 'UPDATE_CORE_BALANCE',
      UPDATE_CORE_SESSION = 'UPDATE_CORE_SESSION'

function createAccount(encryptedBackupPhrase, privateKeychain, email=null) {
  const identityPrivateKeychain = getIdentityPrivateKeychain(privateKeychain)
  const bitcoinPrivateKeychain = getBitcoinPrivateKeychain(privateKeychain)

  const identityPublicKeychain = identityPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')
  const bitcoinPublicKeychain = bitcoinPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')
  const firstIdentityAddress = identityPrivateKeychain.ecPair.getAddress()
  const firstBitcoinAddress = bitcoinPrivateKeychain.ecPair.getAddress()

  const firstIdentityKey = identityPrivateKeychain.ecPair.d.toBuffer(32).toString('hex')
  const firstIdentityKeyID = identityPrivateKeychain.ecPair.getPublicKeyBuffer().toString('hex')

  let analyticsId = identityPublicKeychain
  if (email) {
    analyticsId = email
  }
  mixpanel.track('Create account', { distinct_id: analyticsId })
  mixpanel.track('Perform action', { distinct_id: analyticsId })

  return {
    type: CREATE_ACCOUNT,
    encryptedBackupPhrase: encryptedBackupPhrase,
    identityPublicKeychain: identityPublicKeychain,
    bitcoinPublicKeychain: bitcoinPublicKeychain,
    firstIdentityAddress: firstIdentityAddress,
    firstBitcoinAddress: firstBitcoinAddress,
    firstIdentityKey: firstIdentityKey,
    firstIdentityKeyID: firstIdentityKeyID,
    analyticsId: analyticsId
  }
}

function updateCoreWalletAddress(coreWalletAddress) {
  return {
    type: UPDATE_CORE_ADDRESS,
    coreWalletAddress: coreWalletAddress
  }
}

function updateCoreWalletBalance(coreWalletBalance) {
  return {
    type: UPDATE_CORE_BALANCE,
    coreWalletBalance: coreWalletBalance
  }
}

function deleteAccount() {
  return {
    type: DELETE_ACCOUNT,
    encryptedBackupPhrase: null,
    accountCreated: false
  }
}

function updateBackupPhrase(encryptedBackupPhrase) {
  return {
    type: UPDATE_BACKUP_PHRASE,
    encryptedBackupPhrase: encryptedBackupPhrase
  }
}

function updateBalances(balances) {
  return {
    type: UPDATE_BALANCES,
    balances: balances
  }
}

function updateCoreSessionToken(token) {
   return {
      type: UPDATE_CORE_SESSION,
      coreSessionToken: token,
   };
}

function refreshCoreWalletBalance(addressBalanceUrl, coreWalletAddress) {
  return dispatch => {
    const url = addressBalanceUrl.replace('{address}', coreWalletAddress)
    fetch(url)
    .then((response) => response.text())
    .then((responseText) => JSON.parse(responseText))
    .then((responseJson) => {
      console.log(responseJson)
      const balance = responseJson.unconfirmedBalance + responseJson.balance
      console.log(balance)
      dispatch(
        updateCoreWalletBalance(balance)
      )
    })
  }
}

function getCoreWalletAddress(walletPaymentAddressUrl) {
  return dispatch => {
    const headers = {"Authorization": authorizationHeaderValue() }
    fetch(walletPaymentAddressUrl, { headers: headers })
    .then((response) => response.text())
    .then((responseText) => JSON.parse(responseText))
    .then((responseJson) => {
      const address = responseJson.address
      dispatch(
        updateCoreWalletAddress(address)
      )
    })
  }
}

function getCoreSessionToken(core_host, core_port, privk_app, blockchain_id, auth_request) {
   return dispatch => {
      getCoreSession(core_host, core_port, CORE_API_PASSWORD, privk_app, blockchain_id, auth_request)
        .then((session) => {
           dispatch( updateCoreSessionToken(session) );
        });
   }
}

function refreshBalances(addressBalanceUrl, addresses) {
  return dispatch => {
    let results = []
    addresses.forEach((address) => {

      // fetch balances from https://explorer.blockstack.org/insight-api/addr/{address}/?noTxList=1
      // parse results from: {"addrStr":"1Fvoya7XMvzfpioQnzaskndL7YigwHDnRE","balance":0.02431567,"balanceSat":2431567,"totalReceived":38.82799913,"totalReceivedSat":3882799913,"totalSent":38.80368346,"totalSentSat":3880368346,"unconfirmedBalance":0,"unconfirmedBalanceSat":0,"unconfirmedTxApperances":0,"txApperances":2181}
      const url = addressBalanceUrl.replace('{address}', address)
      fetch(url).then((response) => response.text())
      .then((responseText) => JSON.parse(responseText))
      .then((responseJson) => {

        results.push({
          address: address,
          balance: responseJson['balance']
        })

        if(results.length >= addresses.length) {
          let balances = {}
          let total = 0.0

          for(let i = 0; i < results.length; i++) {
            let address = results[i]['address']
            if(!balances.hasOwnProperty(address)) {
              let balance = results[i]['balance']
              total = total + balance
              balances[address] = balance
            } else {
              console.warn(`Duplicate address ${address} in addresses array`)
            }

          }

          balances['total'] = total

          dispatch(
            updateBalances(balances)
          )
        }
      })
    })
  }
}

function initializeWallet(password, backupPhrase, email=null) {
  return dispatch => {
    let privateKeychain
    if (backupPhrase && bip39.validateMnemonic(backupPhrase)) {
      privateKeychain = PrivateKeychain.fromMnemonic(backupPhrase)
    } else {
      privateKeychain = new PrivateKeychain()
      backupPhrase = privateKeychain.mnemonic()
    }

    encrypt(new Buffer(backupPhrase), password, function(err, ciphertextBuffer) {
      const encryptedBackupPhrase = ciphertextBuffer.toString('hex')
      dispatch(
        createAccount(encryptedBackupPhrase, privateKeychain, email)
      )
    })
  }
}

function newIdentityAddress() {
  return {
    type: NEW_IDENTITY_ADDRESS
  }
}

function newBitcoinAddress() {
  return {
    type: NEW_BITCOIN_ADDRESS
  }
}

export const AccountActions = {
  createAccount: createAccount,
  updateBackupPhrase: updateBackupPhrase,
  initializeWallet: initializeWallet,
  newIdentityAddress: newIdentityAddress,
  newBitcoinAddress: newBitcoinAddress,
  deleteAccount: deleteAccount,
  refreshBalances: refreshBalances,
  getCoreWalletAddress: getCoreWalletAddress,
  refreshCoreWalletBalance: refreshCoreWalletBalance
}

export const AuthActions = {
  getCoreSessionToken: getCoreSessionToken,
}

const initialState = {
  accountCreated: false,
  encryptedBackupPhrase: null,
  identityAccount: {
    addresses: [],
    keypairs: []
  },
  bitcoinAccount: {
    addresses: [],
    balances: { total: 0.0 }
  },
  analyticsId: '',
  coreWalletAddress: null,
  coreWalletBalance: 0.0,
  coreSessionToken: null,
}

export function AccountReducer(state=initialState, action) {
  switch (action.type) {
    case CREATE_ACCOUNT:
      return Object.assign({}, state, {
        accountCreated: true,
        encryptedBackupPhrase: action.encryptedBackupPhrase,
        identityAccount: {
          publicKeychain: action.identityPublicKeychain,
          addresses: [
            action.firstIdentityAddress
          ],
          keypairs: [
            { key: action.firstIdentityKey,
              keyID: action.firstIdentityKeyID,
              address: action.firstIdentityAddress }
          ],
          addressIndex: 0
        },
        bitcoinAccount: {
          publicKeychain: action.bitcoinPublicKeychain,
          addresses: [
            action.firstBitcoinAddress
          ],
          addressIndex: 0,
          balances: state.bitcoinAccount.balances
        },
        analyticsId: action.analyticsId
      })
    case DELETE_ACCOUNT:
      return Object.assign({}, state, {
        accountCreated: false,
        encryptedBackupPhrase: null
      })
    case UPDATE_CORE_ADDRESS:
      return Object.assign({}, state, {
        coreWalletAddress: action.coreWalletAddress
      })
    case UPDATE_CORE_BALANCE:
      return Object.assign({}, state, {
        coreWalletBalance: action.coreWalletBalance
      })
    case UPDATE_BACKUP_PHRASE:
      return Object.assign({}, state, {
        encryptedBackupPhrase: action.encryptedBackupPhrase
      })
    case NEW_IDENTITY_ADDRESS:
      return Object.assign({}, state, {
        identityAccount: {
          publicKeychain: state.identityAccount.publicKeychain,
          addresses: [
            ...state.identityAccount.addresses,
            new PublicKeychain(state.identityAccount.publicKeychain)
              .publiclyEnumeratedChild(state.identityAccount.addressIndex + 1)
              .address().toString()
          ],
          addressIndex: state.identityAccount.addressIndex + 1
        }
      })
    case NEW_BITCOIN_ADDRESS:
      return Object.assign({}, state, {
        bitcoinAccount: {
          publicKeychain: state.bitcoinAccount.publicKeychain,
          addresses: [
            ...state.bitcoinAccount.addresses,
            new PublicKeychain(state.bitcoinAccount.publicKeychain)
              .publiclyEnumeratedChild(state.bitcoinAccount.addressIndex + 1)
              .address().toString()
          ],
          addressIndex: state.bitcoinAccount.addressIndex + 1,
          balances: state.bitcoinAccount.balances
        }
      })
    case UPDATE_BALANCES:
    return Object.assign({}, state, {
      bitcoinAccount: {
        publicKeychain: state.bitcoinAccount.publicKeychain,
        addresses: state.bitcoinAccount.addresses,
        balances: action.balances
      }
    })
     case UPDATE_CORE_SESSION:
        return Object.assign({}, state, {
           coreSessionToken: action.coreSessionToken,
        });

    default:
      return state
  }
}
<|endoftext|>


<commit_before>// Requires for the server-side context. *TODO* Note that `var` is omitted here
// because even within the `if()` IE will wipe globally defined variables if
// `var` is included, leaving us with broken objects.
if (typeof require !== 'undefined') {
    _ = require('underscore')._,
    Backbone = require('backbone.js'),
    Bones = require('bones'),
    require('./models'), // Bones mixin.
    require('./views'); // Bones mixin.
}

var Bones = Bones || {};
Bones.controllers = Bones.controllers || {};

Bones.controllers.Router = Backbone.Controller.extend({
    Collection: Bones.models.Tilesets,
    Model: Bones.models.Tileset,
    initialize: function(options) {
        _.bindAll(this, 'list', 'map', 'getOptions');
    },
    getOptions: function(response) {
        var options = {};
        if (response.req && response.req.model && response.req.model.options) {
            options = response.req.model.options;
        } else if (Bones.settings) {
            options = Bones.settings;
        }
        return options;
    },
    routes: {
        '': 'list',
        '/': 'list',
        '/map/:id': 'map'
    },
    list: function(response) {
        var that = this;
        var options = this.getOptions(response);
        (new this.Collection([], options)).fetch({
            success: function(collection) {
                options.collection = collection;
                options.view = new Bones.views.Maps(options);
                response(new Bones.views.App(options));
            },
            error: _(this.error).bind({options: options, response: response})
        });
    },
    map: function(id, response) {
        var that = this;
        var options = this.getOptions(response);
        (new this.Model({ id: id }, options)).fetch({
            success: function(model) {
                options.model = model;
                options.view = new Bones.views.Map(options);
                response(new Bones.views.App(options));
            },
            error: _(this.error).bind({options: options, response: response})
        });
    },
    // Error view callback. Must have `this.response` and `this.options`.
    error: function(model, xhr) {
        var options = this.options;
        try { options.error = JSON.parse(xhr.responseText).message; }
        catch(err) { options.error = 'Server is offline.'; }

        options.view = new Bones.views.Error(options);
        this.response(new Bones.views.App(options));
    }
});

(typeof module !== 'undefined') && (module.exports = Bones.controllers);

<commit_msg>More general error message for lost connections.<commit_after>// Requires for the server-side context. *TODO* Note that `var` is omitted here
// because even within the `if()` IE will wipe globally defined variables if
// `var` is included, leaving us with broken objects.
if (typeof require !== 'undefined') {
    _ = require('underscore')._,
    Backbone = require('backbone.js'),
    Bones = require('bones'),
    require('./models'), // Bones mixin.
    require('./views'); // Bones mixin.
}

var Bones = Bones || {};
Bones.controllers = Bones.controllers || {};

Bones.controllers.Router = Backbone.Controller.extend({
    Collection: Bones.models.Tilesets,
    Model: Bones.models.Tileset,
    initialize: function(options) {
        _.bindAll(this, 'list', 'map', 'getOptions');
    },
    getOptions: function(response) {
        var options = {};
        if (response.req && response.req.model && response.req.model.options) {
            options = response.req.model.options;
        } else if (Bones.settings) {
            options = Bones.settings;
        }
        return options;
    },
    routes: {
        '': 'list',
        '/': 'list',
        '/map/:id': 'map'
    },
    list: function(response) {
        var that = this;
        var options = this.getOptions(response);
        (new this.Collection([], options)).fetch({
            success: function(collection) {
                options.collection = collection;
                options.view = new Bones.views.Maps(options);
                response(new Bones.views.App(options));
            },
            error: _(this.error).bind({options: options, response: response})
        });
    },
    map: function(id, response) {
        var that = this;
        var options = this.getOptions(response);
        (new this.Model({ id: id }, options)).fetch({
            success: function(model) {
                options.model = model;
                options.view = new Bones.views.Map(options);
                response(new Bones.views.App(options));
            },
            error: _(this.error).bind({options: options, response: response})
        });
    },
    // Error view callback. Must have `this.response` and `this.options`.
    error: function(model, xhr) {
        var options = this.options;
        try { options.error = JSON.parse(xhr.responseText).message; }
        catch(err) { options.error = 'Connection problem.'; }

        options.view = new Bones.views.Error(options);
        this.response(new Bones.views.App(options));
    }
});

(typeof module !== 'undefined') && (module.exports = Bones.controllers);

<|endoftext|>


<commit_before><commit_msg>Removes dirToModule from 404 model<commit_after><|endoftext|>


<commit_before>/* Copyright (c) Royal Holloway, University of London | Contact Blake Loring (blake@parsed.uk), Duncan Mitchell (Duncan.Mitchell.2015@rhul.ac.uk), or Johannes Kinder (johannes.kinder@rhul.ac.uk) for details or support | LICENSE.md for license details */

function buildTestList() {
    var testList = [];

    function buildTest(file, expectPaths, expectErrors) {
        testList.push({
            path: file,
            expectPaths: expectPaths,
            expectErrors: expectErrors
        });
    }

    //Core Javascript, no symbex / annotations
    buildTest('core/bools.js', 1, 0);
    buildTest('core/recursion.js', 1, 0);
    buildTest('core/lamda.js', 1, 0);

    //Booleans
    buildTest('bool/hello.js', 2, 0);
    buildTest('bool/basic.js', 4, 1);

    //Pure Symbols
    buildTest('pure/pure_symbol.js', 8, 0)

    //Integers
    buildTest('integers/hello.js', 2, 0);
    buildTest('integers/lt.js', 3, 0);
    buildTest('integers/coerce.js', 2, 0);
    buildTest('integers/mul.js', 2, 0);
    buildTest('integers/breaker.js', 1, 0);
    buildTest('integers/infoflow.js', 17, 0);

    //Fractions
    buildTest('fractions/fraction_one.js', 3, 0);

    buildTest('assert/assert.js', 6, 0);

    buildTest('assumes/basic.js', 2, 0);
    buildTest('assumes/wrapped_assume.js', 2, 0);

    //Loops
    buildTest('loops/loop_alot.js', 12, 0);

    //Named methods
    buildTest('named_method/simple.js', 1, 0);

    //Async
    buildTest('async/settimeout.js', 3, 1);

    //Strings
    buildTest('strings/hello_strings.js', 2, 0);
    buildTest('strings/hello_strings2.js', 3, 0);
    buildTest('strings/hello_strings_concat.js', 2, 0);
    buildTest('strings/hello_strings_concat2.js', 1, 0);
    buildTest('strings/hello_strings_len.js', 2, 0);
    buildTest('strings/strings_concat.js', 2, 0);
    buildTest('strings/warning.js', 4, 0);

    /**
     * Regular Expression Feature Test
     */

    /**
     * Core language tests
     */
    buildTest('regex/core/alternation/simple.js', 4, 4);
    buildTest('regex/core/alternation/many.js', 4, 4);
    buildTest('regex/core/alternation/words.js', 4, 4);
    buildTest('regex/core/alternation/exhaustive_simple.js', 5, 5);
    buildTest('regex/core/alternation/multiple_related.js', 7, 7);

    buildTest('regex/core/literals/simple_one.js', 2, 1);
    buildTest('regex/core/literals/simple_two.js', 2, 1);
    buildTest('regex/core/literals/long_example.js', 2, 2);
    buildTest('regex/core/literals/empty_example.js', 2, 2);
    buildTest('regex/core/literals/mixed_escaped.js', 3, 3); //TODO: Should this be 2
    buildTest('regex/core/literals/non_alpha.js', 2, 2);
    buildTest('regex/core/literals/multiple.js', 6, 6);

    buildTest('regex/core/escaping/hex.js', 5, 4);
    buildTest('regex/core/escaping/unicode.js', 6, 5);
    buildTest('regex/core/escaping/unicode_mode.js', 6, 5);
    buildTest('regex/core/escaping/ranges.js', 8, 8);
    buildTest('regex/core/escaping/negative_ranges.js', 3, 2);
    buildTest('regex/core/escaping/space_class.js', 8, 7);
    buildTest('regex/core/escaping/word.js', 3, 2);
    buildTest('regex/core/escaping/digit.js', 3, 2);

    buildTest('regex/core/star/star.js', 7, 7);
    buildTest('regex/core/star/online.js', 11, 10);
    buildTest('regex/core/star/lazy.js', 7, 7);
    buildTest('regex/core/star/multiple.js', 5, 5);

    buildTest('regex/core/plus/plus.js', 12, 11);
    buildTest('regex/core/plus/lazy.js', 12, 11);
    buildTest('regex/core/plus/online.js', 11, 10);
    buildTest('regex/core/plus/multiple.js', 4, 4);

    buildTest('regex/core/loops/fixed_loop.js', 3, 2);
    buildTest('regex/core/loops/between_loop.js', 9, 8);
    buildTest('regex/core/loops/minimum_loop.js', 6, 5);

    buildTest('regex/core/optional/base.js', 13, 12);
    buildTest('regex/core/optional/combined.js', 9, 8);
    buildTest('regex/core/optional/no_greed.js', 13, 12);
    buildTest('regex/core/optional/range.js', 3, 2);

    /**
     * Lazy Operator Tests
     */

    buildTest('regex/lazy/lazy_1.js', 3, 2);
    buildTest('regex/lazy/lazy_2.js', 2, 1);
    buildTest('regex/lazy/lazy_3.js', 3, 2);
    buildTest('regex/lazy/lazy_4.js', 2, 1);
    buildTest('regex/lazy/lazy_5.js', 3, 2);
    buildTest('regex/lazy/lazy_6.js', 3, 2);

    /**
     * Anchors Tests
     */
    buildTest('regex/anchors/left.js', 3, 3);
    buildTest('regex/anchors/right.js', 3, 3); //TODO: An extra query is generated
    buildTest('regex/anchors/none.js', 4, 4);
    buildTest('regex/anchors/both.js', 2, 1);

    /**
     * Assertion Tests
     */
    buildTest('regex/assertions/ahead.js', 1, 0);
    buildTest('regex/assertions/ahead_2.js', 2, 1);
    buildTest('regex/assertions/ahead_3.js', 2, 1);
    buildTest('regex/assertions/ahead_4.js', 4, 3);
    buildTest('regex/assertions/ahead_5.js', 4, 3);
    buildTest('regex/assertions/ahead_6.js', 2, 1);
    buildTest('regex/assertions/ahead_7.js', 2, 1);
    buildTest('regex/assertions/ahead_8.js', 2, 1);
    buildTest('regex/assertions/ahead_9.js', 2, 1);

    /**
     * Backreference Tests
     */
    buildTest('regex/backreferences/closed.js', 2, 1);
    buildTest('regex/backreferences/closed_limited.js', 2, 1);
    buildTest('regex/backreferences/closed_range.js', 3, 2);
    buildTest('regex/backreferences/closed_limited.js', 3, 1); //Extra path from assume

    //These we can fail because of restrictions on S
    buildTest('regex/backreferences/closed_loop.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_minor.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_interleaved.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_complex.js', 3, 2);
    buildTest('regex/backreferences/closed_loop_quantified.js', 4, 2); // We fail this test because of the restrictions in the paper

    //Start of open group tests, these will fail often due to restriction on S
    buildTest('regex/backreferences/open.js', 5, 4);
    buildTest('regex/backreferences/open_two.js', 4, 3);
    buildTest('regex/backreferences/open_three.js', 4, 3);
    buildTest('regex/backreferences/open_four.js', 3, 2);

    buildTest('regex/backreferences/open_unlocked.js', 4, 3);
    buildTest('regex/backreferences/open_unlocked_2.js', 4, 3);
    buildTest('regex/backreferences/open_unlocked_3.js', 5, 4);

    /**
     * End of backreference tests
     */

    buildTest('regex/captures/greedy2.js', 3, 2);
    buildTest('regex/captures/greedy_capture.js', 3, 2);
    buildTest('regex/captures/simple.js', 4, 3);
    buildTest('regex/captures/anchors.js', 4, 3);
    buildTest('regex/captures/related.js', 3, 2);
    buildTest('regex/captures/multiple_locked.js', 2, 1);

    buildTest('regex/exec/greed/anchors.js', 4, 3);
    buildTest('regex/exec/greed/nested.js', 4, 3);
    buildTest('regex/exec/greed/optionals.js', 3, 2);
    buildTest('regex/exec/greed/related.js', 3, 2);

    /**
     * Match Tests
     */

    buildTest('regex/match/captures/greedy2.js', 3, 2);
    buildTest('regex/match/captures/greedy_capture.js', 3, 2);
    buildTest('regex/match/captures/simple.js', 4, 3);
    buildTest('regex/match/captures/anchors.js', 4, 3);
    buildTest('regex/match/captures/related.js', 3, 2);
    buildTest('regex/match/captures/multiple_locked.js', 2, 1);

    buildTest('regex/match/greed/anchors.js', 4, 3);
    buildTest('regex/match/greed/nested.js', 4, 3);
    buildTest('regex/match/greed/optionals.js', 3, 2);
    buildTest('regex/match/greed/related.js', 3, 2);

    /**
     * Replace application model tests
     */

     buildTest('regex/replace/single/single_replace.js', 5, 3);
     buildTest('regex/replace/single/replace_2.js', 4, 3);
     buildTest('regex/replace/single/replace_3.js', 5, 4);

     /**
      * Split application model tests
      */

     buildTest('regex/split/split_1', 14, 4);
     buildTest('regex/split/split_2', 6, 0);
     buildTest('regex/split/split_3', 15, 3);
     buildTest('regex/split/split_4', 35, 0); //PC seems a bit high but the test works
     buildTest('regex/split/split_hard', 8, 2);

    /**
     * Sticky model tests
     */
     buildTest('regex/test/flags/sticky', 3, 1);

    /**
     * Search application model tests
     */

    buildTest('regex/search/simple.js', 2, 2);
    buildTest('regex/search/ambiguous1.js', 3, 2);
    buildTest('regex/search/ambiguous2.js', 3, 1); //One extra path spawned by assume command
    buildTest('regex/search/ambiguous3.js', 3, 2); //One extra path spawned by assume command
    buildTest('regex/search/ambiguous4.js', 7, 3); //TODO: Weird results
    buildTest('regex/search/alt.js', 3, 3);
    buildTest('regex/search/not_at_start.js', 3, 3);
    buildTest('regex/search/test_at_start.js', 5, 4);

    /**
     * End of regular expression feature tests
     */

    return testList;
}

exports["default"] = buildTestList();
module.exports = exports["default"];
<commit_msg>Cull expensive test cases<commit_after>/* Copyright (c) Royal Holloway, University of London | Contact Blake Loring (blake@parsed.uk), Duncan Mitchell (Duncan.Mitchell.2015@rhul.ac.uk), or Johannes Kinder (johannes.kinder@rhul.ac.uk) for details or support | LICENSE.md for license details */

function buildTestList() {
    var testList = [];

    function buildTest(file, expectPaths, expectErrors) {
        testList.push({
            path: file,
            expectPaths: expectPaths,
            expectErrors: expectErrors
        });
    }

    //Core Javascript, no symbex / annotations
    buildTest('core/bools.js', 1, 0);
    buildTest('core/recursion.js', 1, 0);
    buildTest('core/lamda.js', 1, 0);

    //Booleans
    buildTest('bool/hello.js', 2, 0);
    buildTest('bool/basic.js', 4, 1);

    //Pure Symbols
    buildTest('pure/pure_symbol.js', 8, 0)

    //Integers
    buildTest('integers/hello.js', 2, 0);
    buildTest('integers/lt.js', 3, 0);
    buildTest('integers/coerce.js', 2, 0);
    buildTest('integers/mul.js', 2, 0);
    buildTest('integers/breaker.js', 1, 0);
    buildTest('integers/infoflow.js', 17, 0);

    //Fractions
    buildTest('fractions/fraction_one.js', 3, 0);

    buildTest('assert/assert.js', 6, 0);

    buildTest('assumes/basic.js', 2, 0);
    buildTest('assumes/wrapped_assume.js', 2, 0);

    //Loops
    buildTest('loops/loop_alot.js', 12, 0);

    //Named methods
    buildTest('named_method/simple.js', 1, 0);

    //Async
    buildTest('async/settimeout.js', 3, 1);

    //Strings
    buildTest('strings/hello_strings.js', 2, 0);
    buildTest('strings/hello_strings2.js', 3, 0);
    buildTest('strings/hello_strings_concat.js', 2, 0);
    buildTest('strings/hello_strings_concat2.js', 1, 0);
    buildTest('strings/hello_strings_len.js', 2, 0);
    buildTest('strings/strings_concat.js', 2, 0);
    buildTest('strings/warning.js', 4, 0);

    /**
     * Regular Expression Feature Test
     */

    /**
     * Core language tests
     */
    buildTest('regex/core/alternation/simple.js', 4, 4);
    buildTest('regex/core/alternation/many.js', 4, 4);
    buildTest('regex/core/alternation/words.js', 4, 4);
    buildTest('regex/core/alternation/exhaustive_simple.js', 5, 5);
    buildTest('regex/core/alternation/multiple_related.js', 7, 7);

    buildTest('regex/core/literals/simple_one.js', 2, 1);
    buildTest('regex/core/literals/simple_two.js', 2, 1);
    buildTest('regex/core/literals/long_example.js', 2, 2);
    buildTest('regex/core/literals/empty_example.js', 2, 2);
    buildTest('regex/core/literals/mixed_escaped.js', 3, 3); //TODO: Should this be 2
    buildTest('regex/core/literals/non_alpha.js', 2, 2);
    buildTest('regex/core/literals/multiple.js', 6, 6);

    buildTest('regex/core/escaping/hex.js', 5, 4);
    buildTest('regex/core/escaping/unicode.js', 6, 5);
    buildTest('regex/core/escaping/unicode_mode.js', 6, 5);
    buildTest('regex/core/escaping/ranges.js', 8, 8);
    buildTest('regex/core/escaping/negative_ranges.js', 3, 2);
    buildTest('regex/core/escaping/space_class.js', 8, 7);
    buildTest('regex/core/escaping/word.js', 3, 2);
    buildTest('regex/core/escaping/digit.js', 3, 2);

    buildTest('regex/core/star/star.js', 7, 7);
    buildTest('regex/core/star/online.js', 11, 10);
    buildTest('regex/core/star/lazy.js', 7, 7);
    buildTest('regex/core/star/multiple.js', 5, 5);

    buildTest('regex/core/plus/plus.js', 12, 11);
    buildTest('regex/core/plus/lazy.js', 12, 11);
    buildTest('regex/core/plus/online.js', 11, 10);
    buildTest('regex/core/plus/multiple.js', 4, 4);

    buildTest('regex/core/loops/fixed_loop.js', 3, 2);
    buildTest('regex/core/loops/between_loop.js', 9, 8);
    buildTest('regex/core/loops/minimum_loop.js', 6, 5);

    buildTest('regex/core/optional/base.js', 13, 12);
    buildTest('regex/core/optional/combined.js', 9, 8);
    buildTest('regex/core/optional/no_greed.js', 13, 12);
    buildTest('regex/core/optional/range.js', 3, 2);

    /**
     * Lazy Operator Tests
     */

    buildTest('regex/lazy/lazy_1.js', 3, 2);
    buildTest('regex/lazy/lazy_2.js', 2, 1);
    buildTest('regex/lazy/lazy_3.js', 3, 2);
    buildTest('regex/lazy/lazy_4.js', 2, 1);
    buildTest('regex/lazy/lazy_5.js', 3, 2);
    buildTest('regex/lazy/lazy_6.js', 3, 2);

    /**
     * Anchors Tests
     */
    //buildTest('regex/anchors/left.js', 3, 3);
    //buildTest('regex/anchors/right.js', 3, 3); //TODO: An extra query is generated
    //buildTest('regex/anchors/none.js', 4, 4);
    buildTest('regex/anchors/both.js', 2, 1);

    /**
     * Assertion Tests
     */
    buildTest('regex/assertions/ahead.js', 1, 0);
    buildTest('regex/assertions/ahead_2.js', 2, 1);
    buildTest('regex/assertions/ahead_3.js', 2, 1);
    buildTest('regex/assertions/ahead_4.js', 4, 3);
    buildTest('regex/assertions/ahead_5.js', 4, 3);
    buildTest('regex/assertions/ahead_6.js', 2, 1);
    buildTest('regex/assertions/ahead_7.js', 2, 1);
    buildTest('regex/assertions/ahead_8.js', 2, 1);
    buildTest('regex/assertions/ahead_9.js', 2, 1);

    /**
     * Backreference Tests
     */
    buildTest('regex/backreferences/closed.js', 2, 1);
    buildTest('regex/backreferences/closed_limited.js', 2, 1);
    buildTest('regex/backreferences/closed_range.js', 3, 2);
    buildTest('regex/backreferences/closed_limited.js', 3, 1); //Extra path from assume

    //These we can fail because of restrictions on S
    /*buildTest('regex/backreferences/closed_loop.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_minor.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_interleaved.js', 2, 1);
    buildTest('regex/backreferences/closed_loop_complex.js', 3, 2);
    buildTest('regex/backreferences/closed_loop_quantified.js', 4, 2); // We fail this test because of the restrictions in the paper

    //Start of open group tests, these will fail often due to restriction on S
    buildTest('regex/backreferences/open.js', 5, 4);
    buildTest('regex/backreferences/open_two.js', 4, 3);
    buildTest('regex/backreferences/open_three.js', 4, 3);
    buildTest('regex/backreferences/open_four.js', 3, 2);

    buildTest('regex/backreferences/open_unlocked.js', 4, 3);
    buildTest('regex/backreferences/open_unlocked_2.js', 4, 3);
    buildTest('regex/backreferences/open_unlocked_3.js', 5, 4);*/

    /**
     * End of backreference tests
     */

    buildTest('regex/captures/greedy2.js', 3, 2);
    buildTest('regex/captures/greedy_capture.js', 3, 2);
    buildTest('regex/captures/simple.js', 4, 3);
    buildTest('regex/captures/anchors.js', 4, 3);
    buildTest('regex/captures/related.js', 3, 2);
    buildTest('regex/captures/multiple_locked.js', 2, 1);

    buildTest('regex/exec/greed/anchors.js', 4, 3);
    //buildTest('regex/exec/greed/nested.js', 4, 3);
    buildTest('regex/exec/greed/optionals.js', 3, 2);
    buildTest('regex/exec/greed/related.js', 3, 2);

    /**
     * Match Tests
     */

    buildTest('regex/match/captures/greedy2.js', 3, 2);
    buildTest('regex/match/captures/greedy_capture.js', 3, 2);
    buildTest('regex/match/captures/simple.js', 4, 3);
    buildTest('regex/match/captures/anchors.js', 4, 3);
    buildTest('regex/match/captures/related.js', 3, 2);
    buildTest('regex/match/captures/multiple_locked.js', 2, 1);

    buildTest('regex/match/greed/anchors.js', 4, 3);
    //buildTest('regex/match/greed/nested.js', 4, 3);
    buildTest('regex/match/greed/optionals.js', 3, 2);
    buildTest('regex/match/greed/related.js', 3, 2);

    /**
     * Replace application model tests
     */

     buildTest('regex/replace/single/single_replace.js', 5, 3);
     buildTest('regex/replace/single/replace_2.js', 4, 3);
     buildTest('regex/replace/single/replace_3.js', 5, 4);

     /**
      * Split application model tests
      */

     buildTest('regex/split/split_1', 14, 4);
     buildTest('regex/split/split_2', 6, 0);
     buildTest('regex/split/split_3', 15, 3);
     buildTest('regex/split/split_4', 35, 0); //PC seems a bit high but the test works
     buildTest('regex/split/split_hard', 8, 2);

    /**
     * Sticky model tests
     */
     buildTest('regex/test/flags/sticky', 3, 1);

    /**
     * Search application model tests
     */

    buildTest('regex/search/simple.js', 2, 2);
    buildTest('regex/search/ambiguous1.js', 3, 2);
    /*buildTest('regex/search/ambiguous2.js', 3, 1); //One extra path spawned by assume command
    buildTest('regex/search/ambiguous3.js', 3, 2); //One extra path spawned by assume command
    buildTest('regex/search/ambiguous4.js', 7, 3); //TODO: Weird results
    buildTest('regex/search/alt.js', 3, 3);
    buildTest('regex/search/not_at_start.js', 3, 3);
    buildTest('regex/search/test_at_start.js', 5, 4);*/

    /**
     * End of regular expression feature tests
     */

    return testList;
}

exports["default"] = buildTestList();
module.exports = exports["default"];
<|endoftext|>


<commit_before>// @flow
import { NARROW_SPACE, WIDE_SPACE, NARROW_BAR, WIDE_BAR } from "../Core/Characters"

const NARROW_WIDTH = 1
const WIDE_WIDTH = 3

export function rect(x: number, wide: boolean, filled: boolean): string {
	return `<rect x="${x}" y="0" width="${wide ? WIDE_WIDTH : NARROW_WIDTH}" height="1" fill="${filled ? "black" : "white"}"/>`
}

export function renderBarcodeToSVG(input: string): string {
	let svg = ""
	let x = 0

	for (const char of input) {
		switch (char) {
			case NARROW_SPACE:
				svg += rect(x, false, false)
				x += NARROW_WIDTH
				break
			case WIDE_SPACE:
				svg += rect(x, true, false)
				x += WIDE_WIDTH
				break
			case NARROW_BAR:
				svg += rect(x, false, true)
				x += NARROW_WIDTH
				break
			case WIDE_BAR:
				svg += rect(x, true, true)
				x += WIDE_WIDTH
				break
		}
	}

	return `<svg viewBox="0 0 ${x} 1" preserveAspectRatio="none">${svg}</svg>`
}
<commit_msg>Implement width and height options<commit_after>// @flow
import { NARROW_SPACE, WIDE_SPACE, NARROW_BAR, WIDE_BAR } from "../Core/Characters"

const NARROW_WIDTH = 1
const WIDE_WIDTH = 3

export function rect(x: number, wide: boolean, filled: boolean): string {
	return `<rect x="${x}" y="0" width="${wide ? WIDE_WIDTH : NARROW_WIDTH}" height="1" fill="${filled ? "black" : "white"}"/>`
}

export function renderBarcodeToSVG(input: string, {width, height}: {width?: number, height?: number} = {}): string {
	let svg = ""
	let x = 0

	for (const char of input) {
		switch (char) {
			case NARROW_SPACE:
				svg += rect(x, false, false)
				x += NARROW_WIDTH
				break
			case WIDE_SPACE:
				svg += rect(x, true, false)
				x += WIDE_WIDTH
				break
			case NARROW_BAR:
				svg += rect(x, false, true)
				x += NARROW_WIDTH
				break
			case WIDE_BAR:
				svg += rect(x, true, true)
				x += WIDE_WIDTH
				break
		}
	}

	let options = [
		`viewBox="0 0 ${x} 1"`,
		`preserveAspectRatio="none"`,
	]
	if (width) {
		options.push(`width="${width}"`)
	}
	if (height) {
		options.push(`height="${height}"`)
	}

	return `<svg ${options.join(" ")}>${svg}</svg>`
}
<|endoftext|>


<commit_before>
var mainCanvas = $('.js-mainCanvas')[0];
var mainContext = mainCanvas.getContext('2d');
mainContext.imageSmoothingEnabled = false;
var bufferCanvas = createCanvas(mainCanvas.width, mainCanvas.height);
var bufferContext = bufferCanvas.getContext('2d');

/////////////////
// lighting

var pointLights = [];

var lightingPixelsPerRow = 100,
    lightingPixelsPerColumn = Math.round(
        mainCanvas.height / mainCanvas.width * lightingPixelsPerRow
    ), // WRONG shouldn't stretch things because we get a half-cell
    lightingPixelsPerGrid = lightingPixelsPerRow * lightingPixelsPerColumn,
    lightingScaledPixelSize = mainCanvas.width / lightingPixelsPerRow, // WRONG not quite right if we're stretching cells vertically to avoid half-cells
    lightingCanvas = $(`<canvas width="${lightingPixelsPerRow}" height="${lightingPixelsPerColumn}" />`)[0],
    lightingContext = lightingCanvas.getContext('2d'),
    lightingData = lightingContext.createImageData(lightingPixelsPerRow, lightingPixelsPerColumn),
    lightingPixelArray = lightingData.data,
    lightingCanvas = document.createElement('canvas'),
    lightingContext = lightingCanvas.getContext('2d'),
    pointLights = [];

lightingCanvas.width = lightingPixelsPerRow;
lightingCanvas.height = lightingPixelsPerColumn;

// Lighting distance table. Usage:
// const dx = Math.round(Math.abs(x1 - x2) / lightingDistanceFactor);
// const dy = Math.round(Math.abs(y1 - y2) / lightingDistanceFactor);
// const distance = lightingDistance[dy][dx];
var lightingDistance = [];
var lightingDistanceFactor = 2;

// Fill in the lighting distance table.
function initializeLighting() {
    const ldf2 = lightingDistanceFactor ** 2;
    for (var i = 0; i < mainCanvas.height / lightingDistanceFactor; i++) {
        lightingDistance[i] = [];
        for (var j = 0; j < mainCanvas.width / lightingDistanceFactor; j++) {
            lightingDistance[i][j] = Math.sqrt(ldf2 * i * i + ldf2 * j * j);
        }
    }
}

initializeLighting();
function removeFinishedPointLights() {
    // This just gets rid of all the point lights that have shouldBeRemoved set to true on them.
    // For now, this will work with point lights that are localSprites.
    pointLights = pointLights.filter(pointLight => !pointLight.shouldBeRemoved);
}

function renderLighting() {
    removeFinishedPointLights();
    //lightingContext.clearRect(0, 0, lightingCanvas.width, lightingCanvas.height); // Is this necessary? If we used a fadeout/decay effect and '+=' at the end (when the actual pixel values are affected) instead of '=' like I do in my "pure sim," we might get more interesting effects, like afterimages and flickering.
    for (var r = 0; r < lightingPixelsPerColumn; r++) {
        const y = (r + .5) * lightingScaledPixelSize;
        for (var c = 0; c < lightingPixelsPerRow; c++) {
            const x = (c + .5) * lightingScaledPixelSize;
            const i = r * lightingPixelsPerRow + c;
            // brightness decay
            // WRONG: eventually this will need to decay toward the precalculated lightmap values, instead of toward 0
            for (var pc = 0; pc < 4; pc++) { // 'pc' means 'pixel channel'
                lightingPixelArray[i * 4 + pc] *= 0.88;
            }
            var red = 0,
                green = 0,
                blue = 0,
                alpha = 0;
            // pointLights
            /*if (pointLights.length > 0) { // if there are point lights active
                    for (var j = 0; j < pointLights.length; j++) { // for each point light
                        var lightX = pointLights[j].x,
                            lightY = pointLights[j].y;
                        // rounding light coordinates, which is necessary for using the distance lookup tables
                        // avoiding Math.round() function calls:
                        // maybe there's a more elegant way to do this.
                        if (lightX % 1 >= 0.5) lightX += 1 - lightX % 1;
                        if (lightX % 1 < 0.5 && lightX % 1 > -0.5) lightX -= lightX % 1;
                        if (lightX % 1 <= -0.5) lightX -= 1 + lightX % 1;
                        if (lightY % 1 >= 0.5) lightY += 1 - lightY % 1;
                        if (lightY % 1 < 0.5 && lightY % 1 > -0.5) lightY -= lightY % 1;
                        if (lightY % 1 <= -0.5) lightY -= 1 + lightY % 1;
                        if (frameCounter % 15 === 0 && j === 0 && i === 0) {
                            console.log(

                            );
                        }
                        r = 0;
                        g = 0;
                        b = 0;
                        a = 0;
                        // WRONG: Should express these values as proportions of the first so that all this calculation doesn't have to happen repeatedly.
                        //      The speed gain might not be worth it, but it's really important that the lighting be efficient, so maybe it really is worth it.
                        // WRONG: eventually I'll transplant my neighborsOfIndexInRadius[][] array in from my pixel project and we can set
                        //      a limited radius to which cells a point light affects.
                        r += 768 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                        g += 384 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                        b += 64;//384 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[light.x][light.y]];
                        a += 128 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                    }
                }*/
            // sun point light
            var sun = {x: mainCharacter.x - cameraX, y: mainCharacter.y - cameraY - 80};
            // `(A + .5) << 1 >> 1;` Does the same thing as `Math.round(A)`, but is a little bit faster because
            // it doesn't have to invoke a function.
            var dx = ((sun.x - x) / lightingDistanceFactor + .5) << 1 >> 1;
            var dy = ((sun.y - y) / lightingDistanceFactor + .5) << 1 >> 1;
            if (dx < 0) dx = -dx;
            if (dy < 0) dy = -dy;
            // These lines should do the same as the above 4, using functions.
            // var dx = Math.abs(Math.round((sun.x - x) / lightingDistanceFactor));
            // var dy = Math.abs(Math.round((sun.x - y) / lightingDistanceFactor));
            // I added a factor of 8 here because without it the sun looked too small in this version.
            const distance = lightingDistance[dy][dx];
            red += 768 / distance;
            green += 384 / distance;
            blue += 64;//384 / distance;
            alpha += 128 / distance;

            // haze
            var maxHaze = mainCanvas.height - y;
            if (maxHaze > 80) maxHaze = 80;
            if (maxHaze < 10) maxHaze = 10;
            red += 128 / maxHaze;
            green += 128 / maxHaze;
            blue += 64 / maxHaze;
            alpha += 128 / maxHaze;

            if (distance > 100) {
                red = 0;
                green = 0;
                blue = 0;
                alpha = 255 * (distance - 100) / 1000;
            }

            // logging
            if (frameCounter % 15 === 0 && i === 0) {
                console.log(

                );
            }

            // for each pixel, add the sum of all dynamic lighting this frame
            lightingPixelArray[i * 4 + 0] += red;
            lightingPixelArray[i * 4 + 1] += green;
            lightingPixelArray[i * 4 + 2] += blue;
            lightingPixelArray[i * 4 + 3] += alpha;
        }
    }
    // draw pixelArray
    lightingContext.putImageData(lightingData, 0, 0);
    // turn on antialiasing just for the lighting grid
    mainContext.imageSmoothingEnabled = true;
    // scale pixelArray up to canvas size
    mainContext.drawImage(lightingCanvas, 0, 0, lightingCanvas.width, lightingCanvas.height, 0, 0, mainCanvas.width, mainCanvas.height);
    // turning off antialiasing for everything else
    mainContext.imageSmoothingEnabled = false;
}
// end lighting
///////////////////

var render = () => {
    //countFps(5, 30, FPSRENDER); // just comment this in for an FPS display in the console.
    try {
    if (!gameHasBeenInitialized || !currentMap) {
        window.requestAnimationFrame(render);
        return;
    }

    //var bgSourceRectangle = new Rectangle(0, 0, 1920, 1080);
    var bgSourceRectangle = new Rectangle(0, 0, 800, 608);
    var target = bgSourceRectangle.scale(1.2); // used to be 0.6 when the background pic was yellowMountains.png
    var xPercent = (cameraX / (Math.max(areaRectangle.width, target.width) - mainCanvas.width)) || 0;
    if (areaRectangle.width < mainCanvas.width) xPercent = 0;
    var yPercent = (cameraY / (Math.max(areaRectangle.height, target.height) - mainCanvas.height)) || 0;
    if (areaRectangle.height < mainCanvas.height) yPercent = 0;
    target = target.moveTo(- xPercent * (target.width - mainCanvas.width), - yPercent * (target.height - mainCanvas.height));

    var taggedPlayer = TagGame.getTaggedPlayer();
    draw.fillRectangle(mainContext, new Rectangle(0, 0, mainCanvas.width, mainCanvas.height), 0);
    //if (taggedPlayer) {
    //    draw.tintedImage(mainContext, requireImage('/gfx/backgrounds/yellowMountains.png'), taggedPlayer.color, .5, bgSourceRectangle, target)
    //} else {
//    draw.image(mainContext, requireImage('/gfx/backgrounds/yellowMountains.png'), bgSourceRectangle, target);
    draw.image(mainContext, requireImage('/gfx/backgrounds/desertBackgroundA.png'), bgSourceRectangle, target);
    //}

    drawMap();
    mainContext.save();
    mainContext.translate(Math.round(-cameraX), Math.round(-cameraY));
    // Update all the sprites that the game keeps track of
    for (var sprite of
        [
            // All the characters from other clients.
            ...Object.values(otherCharacters),
            // The main character for the client is drawn after the other characters
            // so that it will always appear in front of them.
            mainCharacter,
            // Other sprite objects like fireballs, particles, explosions and triggers.
            ...localSprites,
        ]
    ) {
        sprite.render(sprite);
    }
    mainContext.restore();
    if (isEditing) {
        renderEditor();
        window.requestAnimationFrame(render);
        return;
    }

    // Draw HUD elements here like the life display for the main character.
    mainContext.save();
    mainContext.translate(10, 10);
    var heartImage = requireImage('/gfx/heart.png');
    var heartRectangle = new Rectangle(0, 0, 50, 50);
    for (var i = 0; i < mainCharacter.maxHealth; i++) {
        if (i < mainCharacter.health) draw.image(mainContext, heartImage, heartRectangle, heartRectangle);
        else draw.solidTintedImage(mainContext, heartImage, '#444', heartRectangle, heartRectangle);
        mainContext.translate(60, 0);
    }
    mainContext.restore();

    if (mainCharacter.changingZones) {
        mainContext.save();
        mainContext.globalAlpha = (now() - mainCharacter.changingZones) / 500;
        draw.fillRectangle(mainContext, new Rectangle(0, 0, mainCanvas.width, mainCanvas.height), 0);
        mainContext.restore();
    }

    TagGame.render();

    // Considering calculating hit box from the animation. But do I want to worry about rotation with this?
    /*var frame = mainCharacter.walkingAnimation.frames[0];
    var hitBox = frame.hitBox;
    hitBox = rectangle(mainCharacter.x - frame.width / 2 + hitBox.left)*/

    // Draw a rectangle where we expect the sprite to be displayed for the main character.
    // draw.fillRectangle(mainContext, rectangle(mainCharacter.x - 2, mainCharacter.y - 2, 4, 4), 'white');

    window.requestAnimationFrame(render);
    } catch (e) {
        console.log(e);
        debugger;
    }
    renderLighting();
};
var drawMap = () => {
    var topRow = Math.floor((cameraY - mapTop) / currentMap.tileSize);
    var bottomRow = Math.ceil((cameraY - mapTop + mainCanvas.height) / currentMap.tileSize);
    var leftColumn = Math.floor((cameraX - mapLeft) / currentMap.tileSize);
    var rightColumn = Math.ceil((cameraX - mapLeft + mainCanvas.width) / currentMap.tileSize);
    mainContext.save();
    mainContext.translate(Math.round(-cameraX), Math.round(-cameraY));
    mainContext.translate(0, currentMap.tileSize * topRow + currentMap.tileSize / 2);
    for (var row = topRow; row < bottomRow; row++) {
        if (!currentMap.composite[row]) {
            mainContext.translate(0, currentMap.tileSize);
            continue;
        }
        mainContext.save();
        mainContext.translate(currentMap.tileSize * leftColumn + currentMap.tileSize / 2, 0);
        for (var col = leftColumn; col < rightColumn; col++) {
            var tile = currentMap.uniqueTiles[currentMap.composite[row][col]];
            if (tile) {
                var image = requireImage(tile.image);
                mainContext.save();
                mainContext.scale(tile.xScale, tile.yScale);
                draw.image(mainContext, image,
                    new Rectangle(tile.x, tile.y, 1, 1).scale(tile.size),
                    new Rectangle(-1 / 2, -1 / 2, 1, 1).scale(currentMap.tileSize)
                );
                mainContext.restore();
            }
            mainContext.translate(currentMap.tileSize, 0);
        }
        mainContext.restore();
        mainContext.translate(0, currentMap.tileSize);
    }
    mainContext.restore();
}

render();
<commit_msg>Tiny haze color tweak.<commit_after>
var mainCanvas = $('.js-mainCanvas')[0];
var mainContext = mainCanvas.getContext('2d');
mainContext.imageSmoothingEnabled = false;
var bufferCanvas = createCanvas(mainCanvas.width, mainCanvas.height);
var bufferContext = bufferCanvas.getContext('2d');

/////////////////
// lighting

var pointLights = [];

var lightingPixelsPerRow = 100,
    lightingPixelsPerColumn = Math.round(
        mainCanvas.height / mainCanvas.width * lightingPixelsPerRow
    ), // WRONG shouldn't stretch things because we get a half-cell
    lightingPixelsPerGrid = lightingPixelsPerRow * lightingPixelsPerColumn,
    lightingScaledPixelSize = mainCanvas.width / lightingPixelsPerRow, // WRONG not quite right if we're stretching cells vertically to avoid half-cells
    lightingCanvas = $(`<canvas width="${lightingPixelsPerRow}" height="${lightingPixelsPerColumn}" />`)[0],
    lightingContext = lightingCanvas.getContext('2d'),
    lightingData = lightingContext.createImageData(lightingPixelsPerRow, lightingPixelsPerColumn),
    lightingPixelArray = lightingData.data,
    lightingCanvas = document.createElement('canvas'),
    lightingContext = lightingCanvas.getContext('2d'),
    pointLights = [];

lightingCanvas.width = lightingPixelsPerRow;
lightingCanvas.height = lightingPixelsPerColumn;

// Lighting distance table. Usage:
// const dx = Math.round(Math.abs(x1 - x2) / lightingDistanceFactor);
// const dy = Math.round(Math.abs(y1 - y2) / lightingDistanceFactor);
// const distance = lightingDistance[dy][dx];
var lightingDistance = [];
var lightingDistanceFactor = 2;

// Fill in the lighting distance table.
function initializeLighting() {
    const ldf2 = lightingDistanceFactor ** 2;
    for (var i = 0; i < mainCanvas.height / lightingDistanceFactor; i++) {
        lightingDistance[i] = [];
        for (var j = 0; j < mainCanvas.width / lightingDistanceFactor; j++) {
            lightingDistance[i][j] = Math.sqrt(ldf2 * i * i + ldf2 * j * j);
        }
    }
}

initializeLighting();
function removeFinishedPointLights() {
    // This just gets rid of all the point lights that have shouldBeRemoved set to true on them.
    // For now, this will work with point lights that are localSprites.
    pointLights = pointLights.filter(pointLight => !pointLight.shouldBeRemoved);
}

function renderLighting() {
    removeFinishedPointLights();
    //lightingContext.clearRect(0, 0, lightingCanvas.width, lightingCanvas.height); // Is this necessary? If we used a fadeout/decay effect and '+=' at the end (when the actual pixel values are affected) instead of '=' like I do in my "pure sim," we might get more interesting effects, like afterimages and flickering.
    for (var r = 0; r < lightingPixelsPerColumn; r++) {
        const y = (r + .5) * lightingScaledPixelSize;
        for (var c = 0; c < lightingPixelsPerRow; c++) {
            const x = (c + .5) * lightingScaledPixelSize;
            const i = r * lightingPixelsPerRow + c;
            // brightness decay
            // WRONG: eventually this will need to decay toward the precalculated lightmap values, instead of toward 0
            for (var pc = 0; pc < 4; pc++) { // 'pc' means 'pixel channel'
                lightingPixelArray[i * 4 + pc] *= 0.88;
            }
            var red = 0,
                green = 0,
                blue = 0,
                alpha = 0;
            // pointLights
            /*if (pointLights.length > 0) { // if there are point lights active
                    for (var j = 0; j < pointLights.length; j++) { // for each point light
                        var lightX = pointLights[j].x,
                            lightY = pointLights[j].y;
                        // rounding light coordinates, which is necessary for using the distance lookup tables
                        // avoiding Math.round() function calls:
                        // maybe there's a more elegant way to do this.
                        if (lightX % 1 >= 0.5) lightX += 1 - lightX % 1;
                        if (lightX % 1 < 0.5 && lightX % 1 > -0.5) lightX -= lightX % 1;
                        if (lightX % 1 <= -0.5) lightX -= 1 + lightX % 1;
                        if (lightY % 1 >= 0.5) lightY += 1 - lightY % 1;
                        if (lightY % 1 < 0.5 && lightY % 1 > -0.5) lightY -= lightY % 1;
                        if (lightY % 1 <= -0.5) lightY -= 1 + lightY % 1;
                        if (frameCounter % 15 === 0 && j === 0 && i === 0) {
                            console.log(

                            );
                        }
                        r = 0;
                        g = 0;
                        b = 0;
                        a = 0;
                        // WRONG: Should express these values as proportions of the first so that all this calculation doesn't have to happen repeatedly.
                        //      The speed gain might not be worth it, but it's really important that the lighting be efficient, so maybe it really is worth it.
                        // WRONG: eventually I'll transplant my neighborsOfIndexInRadius[][] array in from my pixel project and we can set
                        //      a limited radius to which cells a point light affects.
                        r += 768 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                        g += 384 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                        b += 64;//384 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[light.x][light.y]];
                        a += 128 / lightingDistanceFromIndexToIndex[i][lightingIndexOfCoordinates[lightX][lightY]];
                    }
                }*/
            // sun point light
            var sun = {x: mainCharacter.x - cameraX, y: mainCharacter.y - cameraY - 80};
            // `(A + .5) << 1 >> 1;` Does the same thing as `Math.round(A)`, but is a little bit faster because
            // it doesn't have to invoke a function.
            var dx = ((sun.x - x) / lightingDistanceFactor + .5) << 1 >> 1;
            var dy = ((sun.y - y) / lightingDistanceFactor + .5) << 1 >> 1;
            if (dx < 0) dx = -dx;
            if (dy < 0) dy = -dy;
            // These lines should do the same as the above 4, using functions.
            // var dx = Math.abs(Math.round((sun.x - x) / lightingDistanceFactor));
            // var dy = Math.abs(Math.round((sun.x - y) / lightingDistanceFactor));
            // I added a factor of 8 here because without it the sun looked too small in this version.
            const distance = lightingDistance[dy][dx];
            red += 768 / distance;
            green += 384 / distance;
            blue += 256 / distance;
            alpha += 128 / distance;

            // haze
            var maxHaze = mainCanvas.height - y;
            if (maxHaze > 80) maxHaze = 80;
            if (maxHaze < 10) maxHaze = 10;
            red += 128 / maxHaze;
            green += 128 / maxHaze;
            blue += 64 / maxHaze;
            alpha += 128 / maxHaze;

            if (distance > 100) {
                red = 0;
                green = 0;
                blue = 0;
                alpha = 255 * (distance - 100) / 1000;
            }

            // logging
            if (frameCounter % 15 === 0 && i === 0) {
                console.log(

                );
            }

            // for each pixel, add the sum of all dynamic lighting this frame
            lightingPixelArray[i * 4 + 0] += red;
            lightingPixelArray[i * 4 + 1] += green;
            lightingPixelArray[i * 4 + 2] += blue;
            lightingPixelArray[i * 4 + 3] += alpha;
        }
    }
    // draw pixelArray
    lightingContext.putImageData(lightingData, 0, 0);
    // turn on antialiasing just for the lighting grid
    mainContext.imageSmoothingEnabled = true;
    // scale pixelArray up to canvas size
    mainContext.drawImage(lightingCanvas, 0, 0, lightingCanvas.width, lightingCanvas.height, 0, 0, mainCanvas.width, mainCanvas.height);
    // turning off antialiasing for everything else
    mainContext.imageSmoothingEnabled = false;
}
// end lighting
///////////////////

var render = () => {
    //countFps(5, 30, FPSRENDER); // just comment this in for an FPS display in the console.
    try {
    if (!gameHasBeenInitialized || !currentMap) {
        window.requestAnimationFrame(render);
        return;
    }

    //var bgSourceRectangle = new Rectangle(0, 0, 1920, 1080);
    var bgSourceRectangle = new Rectangle(0, 0, 800, 608);
    var target = bgSourceRectangle.scale(1.2); // used to be 0.6 when the background pic was yellowMountains.png
    var xPercent = (cameraX / (Math.max(areaRectangle.width, target.width) - mainCanvas.width)) || 0;
    if (areaRectangle.width < mainCanvas.width) xPercent = 0;
    var yPercent = (cameraY / (Math.max(areaRectangle.height, target.height) - mainCanvas.height)) || 0;
    if (areaRectangle.height < mainCanvas.height) yPercent = 0;
    target = target.moveTo(- xPercent * (target.width - mainCanvas.width), - yPercent * (target.height - mainCanvas.height));

    var taggedPlayer = TagGame.getTaggedPlayer();
    draw.fillRectangle(mainContext, new Rectangle(0, 0, mainCanvas.width, mainCanvas.height), 0);
    //if (taggedPlayer) {
    //    draw.tintedImage(mainContext, requireImage('/gfx/backgrounds/yellowMountains.png'), taggedPlayer.color, .5, bgSourceRectangle, target)
    //} else {
//    draw.image(mainContext, requireImage('/gfx/backgrounds/yellowMountains.png'), bgSourceRectangle, target);
    draw.image(mainContext, requireImage('/gfx/backgrounds/desertBackgroundA.png'), bgSourceRectangle, target);
    //}

    drawMap();
    mainContext.save();
    mainContext.translate(Math.round(-cameraX), Math.round(-cameraY));
    // Update all the sprites that the game keeps track of
    for (var sprite of
        [
            // All the characters from other clients.
            ...Object.values(otherCharacters),
            // The main character for the client is drawn after the other characters
            // so that it will always appear in front of them.
            mainCharacter,
            // Other sprite objects like fireballs, particles, explosions and triggers.
            ...localSprites,
        ]
    ) {
        sprite.render(sprite);
    }
    mainContext.restore();
    if (isEditing) {
        renderEditor();
        window.requestAnimationFrame(render);
        return;
    }

    // Draw HUD elements here like the life display for the main character.
    mainContext.save();
    mainContext.translate(10, 10);
    var heartImage = requireImage('/gfx/heart.png');
    var heartRectangle = new Rectangle(0, 0, 50, 50);
    for (var i = 0; i < mainCharacter.maxHealth; i++) {
        if (i < mainCharacter.health) draw.image(mainContext, heartImage, heartRectangle, heartRectangle);
        else draw.solidTintedImage(mainContext, heartImage, '#444', heartRectangle, heartRectangle);
        mainContext.translate(60, 0);
    }
    mainContext.restore();

    if (mainCharacter.changingZones) {
        mainContext.save();
        mainContext.globalAlpha = (now() - mainCharacter.changingZones) / 500;
        draw.fillRectangle(mainContext, new Rectangle(0, 0, mainCanvas.width, mainCanvas.height), 0);
        mainContext.restore();
    }

    TagGame.render();

    // Considering calculating hit box from the animation. But do I want to worry about rotation with this?
    /*var frame = mainCharacter.walkingAnimation.frames[0];
    var hitBox = frame.hitBox;
    hitBox = rectangle(mainCharacter.x - frame.width / 2 + hitBox.left)*/

    // Draw a rectangle where we expect the sprite to be displayed for the main character.
    // draw.fillRectangle(mainContext, rectangle(mainCharacter.x - 2, mainCharacter.y - 2, 4, 4), 'white');

    window.requestAnimationFrame(render);
    } catch (e) {
        console.log(e);
        debugger;
    }
    renderLighting();
};
var drawMap = () => {
    var topRow = Math.floor((cameraY - mapTop) / currentMap.tileSize);
    var bottomRow = Math.ceil((cameraY - mapTop + mainCanvas.height) / currentMap.tileSize);
    var leftColumn = Math.floor((cameraX - mapLeft) / currentMap.tileSize);
    var rightColumn = Math.ceil((cameraX - mapLeft + mainCanvas.width) / currentMap.tileSize);
    mainContext.save();
    mainContext.translate(Math.round(-cameraX), Math.round(-cameraY));
    mainContext.translate(0, currentMap.tileSize * topRow + currentMap.tileSize / 2);
    for (var row = topRow; row < bottomRow; row++) {
        if (!currentMap.composite[row]) {
            mainContext.translate(0, currentMap.tileSize);
            continue;
        }
        mainContext.save();
        mainContext.translate(currentMap.tileSize * leftColumn + currentMap.tileSize / 2, 0);
        for (var col = leftColumn; col < rightColumn; col++) {
            var tile = currentMap.uniqueTiles[currentMap.composite[row][col]];
            if (tile) {
                var image = requireImage(tile.image);
                mainContext.save();
                mainContext.scale(tile.xScale, tile.yScale);
                draw.image(mainContext, image,
                    new Rectangle(tile.x, tile.y, 1, 1).scale(tile.size),
                    new Rectangle(-1 / 2, -1 / 2, 1, 1).scale(currentMap.tileSize)
                );
                mainContext.restore();
            }
            mainContext.translate(currentMap.tileSize, 0);
        }
        mainContext.restore();
        mainContext.translate(0, currentMap.tileSize);
    }
    mainContext.restore();
}

render();
<|endoftext|>


<commit_before>(function () {
var undefined;

function OutOfRange () { };
var BeforeStart = new OutOfRange();
var AfterEnd = new OutOfRange();

/* Usage:
var interpolate = new Interpol( [[0, 0], [5, 10]], 0 );
interpolate.by(2); //=> [2, 4];
*/

function makeNewEmpty(object) {
	return (Object.prototype.toString.call(object) === '[object Array]')? [] : {};
}

var Interpol = function (points, key) {
	var me = this;

	function mix (leftPoint, rightPoint, relativePosition) {
		var o = makeNewEmpty(leftPoint);
		for (var key in leftPoint) {
			var val = leftPoint[key] * (1 - relativePosition)
				+ rightPoint[key] * relativePosition;
			if (!isNaN(val)) o[key] = val;
		}
		return o;
	}

	function find (value) {
		var leftIndex = points.length - 1;

		if (points[leftIndex][key] < value) return AfterEnd;
		if (points[0][key] > value) return BeforeStart;

		while (leftIndex >= 0 && points[leftIndex][key] > value) leftIndex--;

		var rightIndex = Math.min(leftIndex + 1, points.length - 1);

		var deltaRightLeft = points[rightIndex][key] - points[leftIndex][key];
		var deltaValueLeft = value - points[leftIndex][key];
		var relativePosition = deltaValueLeft/deltaRightLeft;

		return [leftIndex, rightIndex, relativePosition];
	}

	function interpolate (value) {
		var p = find(value);
		if (p instanceof OutOfRange) return false;
		return mix(points[p[0]], points[p[1]], p[2]);
	}

	function interpolateUpTo (value) {
		var p = find(value);
		if (p === BeforeStart) return false;
		var r = points.slice(0, p[1]);
		r.push(mix(points[p[0]], points[p[1]], p[2]));
		return r;
	}

	this.by = interpolate;
	this.until = interpolateUpTo;
}

window.M.Interpol = Interpol;

})();
<commit_msg>Made search more efficient<commit_after>(function () {
var undefined;

function OutOfRange () { };
var BeforeStart = new OutOfRange();
var AfterEnd = new OutOfRange();

/* Usage:
var interpolate = new Interpol( [[0, 0], [5, 10]], 0 );
interpolate.by(2); //=> [2, 4];
*/

function makeNewEmpty(object) {
	return (Object.prototype.toString.call(object) === '[object Array]')? [] : {};
}

var Interpol = function (points, key) {
	var me = this;

	var first = points[0];
	var last = points[points.length-1];
	var range = last[key]-first[key];

	function mix (leftPoint, rightPoint, relativePosition) {
		var o = makeNewEmpty(leftPoint);
		for (var key in leftPoint) {
			var val = leftPoint[key] * (1 - relativePosition)
				+ rightPoint[key] * relativePosition;
			if (!isNaN(val)) o[key] = val;
		}
		return o;
	}

	function find (value) {
		// No binary search, but an informed linear search
		if (last[key] <= value) return AfterEnd;
		if (first[0][key] >= value) return BeforeStart;

		var relativeValue = (value - first[key]) / range;
		var i = (relativeValue * points.length-1)|0;

		var found = false;
		while (!found) {
			if (points[i+1][key] <= value) {
				i++;
			} else if (points[i][key] > value) {
				i--;
			} else {
				found = true;
			}
		}
		var relativePosition = (value - points[i][key])/(points[i+1][key] - points[i][key]);

		return [i, i+1, relativePosition];
	}

	function interpolate (value) {
		var p = find(value);
		if (p instanceof OutOfRange) return false;
		return mix(points[p[0]], points[p[1]], p[2]);
	}

	function interpolateUpTo (value) {
		var p = find(value);
		if (p === BeforeStart) return false;
		var r = points.slice(0, p[1]);
		r.push(mix(points[p[0]], points[p[1]], p[2]));
		return r;
	}

	this.by = interpolate;
	this.until = interpolateUpTo;
}

window.M.Interpol = Interpol;

})();
<|endoftext|>


<commit_before>

// function payWall(){
//     var xhrpw = new XMLHttpRequest();
//     xhrpw.open('get', '/index.php/jsapi/paywall');
//     xhrpw.setRequestHeader('Content-Type', 'application/text');
//     xhrpw.onload = function() {
//         if (xhrpw.status === 200) {
//            isReqSuccess = true;
//             var data = xhrpw.responseText;
//             var dataObj = JSON.parse(data);
//             if (dataObj.paywall >= 1) {
//                 updateUnlockClass();
//             }else{
//                 updateLockClass();
//                 // console.log('open lock class');
//             }
//         } else {
//             console.log('fail to request');
//         }
//     };
//     xhrpw.send(null);
// }

// var userId1 = GetCookie('USER_ID') ;
// if (userId1 !== null) {
//     payWall();
//     var interval = setInterval(function(){
//         payWall();
//     },5000);
//     setTimeout(function( ) {
//       clearInterval(interval);
//     }, 10000);
// }

var isReqSuccess = false;
var i = 0;
function payWall(){
if(!isReqSuccess && i<3){
      var xhrpw = new XMLHttpRequest();
      xhrpw.open('get', '/index.php/jsapi/paywall');
      xhrpw.setRequestHeader('Content-Type', 'application/text');
      xhrpw.onload = function() {
          if (xhrpw.status === 200) {
            isReqSuccess = true;
              var data = xhrpw.responseText;
              var dataObj = JSON.parse(data);
              if (dataObj.paywall >= 1) {
                  updateUnlockClass();
              }else{
                  updateLockClass();
              }
          } else {
              isReqSuccess = false;
              i++;
              setTimeout(function() {
                  payWall();
              }, 500);
              console.log('fail to request:'+i);
          }
      };
      xhrpw.send(null);
    }
}

var userId1 = GetCookie('USER_ID') ;
if (userId1 !== null) {
  payWall();
}

// 过滤出包含locked的item-headline数组
function getPayStory(className){
  var itemHeadline = document.querySelectorAll('.item-headline');
  var getPayHeadline = [];
  // 循环itemHeadline长度数量
  for (var i = 0; i < itemHeadline.length; i++) {
        var childNodes = itemHeadline[i].children;
        // 循环childNodes长度数量
        for (var j = 0; j < childNodes.length; j++) {
          if (hasClass(childNodes[j],className)){
            getPayHeadline.push(childNodes[j]);
          }
        }
  }
  console.log('getPayHeadline len:'+getPayHeadline.length);
  return getPayHeadline;
}

function updateLockClass(){
  var getPayHeadline = getPayStory('locked');
  if (getPayHeadline.length>0){
    for (var k = 0; k < getPayHeadline.length; k++) {
      removeClass(getPayHeadline[k], 'locked');
      addClass(getPayHeadline[k], 'unlocked');
    }
  }
}
function updateUnlockClass(){
    var getPayHeadline = getPayStory('unlocked');
    if (getPayHeadline.length>0){
      for (var k = 0; k < getPayHeadline.length; k++) {
        removeClass(getPayHeadline[k], 'unlocked');
        addClass(getPayHeadline[k], 'locked');
      }
    }
}

function hasClass(ele, cls) {
  cls = cls || '';
  if (cls.replace(/\s/g, '').length === 0) {
    return false;
  }else{
    return new RegExp(' ' + cls + ' ').test(' ' + ele.className + ' ');
  }

}

function addClass(ele, cls) {
  if (!hasClass(ele, cls)) {
    ele.className = ele.className === '' ? cls : ele.className + ' ' + cls;
  }
}

function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    var newClass = ' ' + ele.className.replace(/[\t\r\n]/g, '') + ' ';
    while (newClass.indexOf(' ' + cls + ' ') >= 0) {
      newClass = newClass.replace(' ' + cls + ' ', ' ');
    }
    ele.className = newClass.replace(/^\s+|\s+$/g, '');
  }
}

// 过滤出包含a的子节点，然后用过滤出的节点增加class
// function getHeadlineA(ele,clsName){
//     var childNodes = ele.children;   //HTMLCollection
//     for (let i = 0; i < childNodes.length; i++) {
//       if (childNodes[i].tagName.toLowerCase()==='a'){
//         addClass(childNodes[i], clsName);
//       }
//     }
// }

<commit_msg>delete console for paywall<commit_after>

// function payWall(){
//     var xhrpw = new XMLHttpRequest();
//     xhrpw.open('get', '/index.php/jsapi/paywall');
//     xhrpw.setRequestHeader('Content-Type', 'application/text');
//     xhrpw.onload = function() {
//         if (xhrpw.status === 200) {
//            isReqSuccess = true;
//             var data = xhrpw.responseText;
//             var dataObj = JSON.parse(data);
//             if (dataObj.paywall >= 1) {
//                 updateUnlockClass();
//             }else{
//                 updateLockClass();
//                 // console.log('open lock class');
//             }
//         } else {
//             console.log('fail to request');
//         }
//     };
//     xhrpw.send(null);
// }

// var userId1 = GetCookie('USER_ID') ;
// if (userId1 !== null) {
//     payWall();
//     var interval = setInterval(function(){
//         payWall();
//     },5000);
//     setTimeout(function( ) {
//       clearInterval(interval);
//     }, 10000);
// }

var isReqSuccess = false;
var i = 0;
function payWall(){
if(!isReqSuccess && i<3){
      var xhrpw = new XMLHttpRequest();
      xhrpw.open('get', '/index.php/jsapi/paywall');
      xhrpw.setRequestHeader('Content-Type', 'application/text');
      xhrpw.onload = function() {
          if (xhrpw.status === 200) {
            isReqSuccess = true;
              var data = xhrpw.responseText;
              var dataObj = JSON.parse(data);
              if (dataObj.paywall >= 1) {
                  updateUnlockClass();
              }else{
                  updateLockClass();
              }
          } else {
              isReqSuccess = false;
              i++;
              setTimeout(function() {
                  payWall();
              }, 500);
              console.log('fail to request:'+i);
          }
      };
      xhrpw.send(null);
    }
}

var userId1 = GetCookie('USER_ID') ;
if (userId1 !== null) {
  payWall();
}

// 过滤出包含locked的item-headline数组
function getPayStory(className){
  var itemHeadline = document.querySelectorAll('.item-headline');
  var getPayHeadline = [];
  // 循环itemHeadline长度数量
  for (var i = 0; i < itemHeadline.length; i++) {
        var childNodes = itemHeadline[i].children;
        // 循环childNodes长度数量
        for (var j = 0; j < childNodes.length; j++) {
          if (hasClass(childNodes[j],className)){
            getPayHeadline.push(childNodes[j]);
          }
        }
  }
  // console.log('getPayHeadline len:'+getPayHeadline.length);
  return getPayHeadline;
}

function updateLockClass(){
  var getPayHeadline = getPayStory('locked');
  if (getPayHeadline.length>0){
    for (var k = 0; k < getPayHeadline.length; k++) {
      removeClass(getPayHeadline[k], 'locked');
      addClass(getPayHeadline[k], 'unlocked');
    }
  }
}
function updateUnlockClass(){
    var getPayHeadline = getPayStory('unlocked');
    if (getPayHeadline.length>0){
      for (var k = 0; k < getPayHeadline.length; k++) {
        removeClass(getPayHeadline[k], 'unlocked');
        addClass(getPayHeadline[k], 'locked');
      }
    }
}

function hasClass(ele, cls) {
  cls = cls || '';
  if (cls.replace(/\s/g, '').length === 0) {
    return false;
  }else{
    return new RegExp(' ' + cls + ' ').test(' ' + ele.className + ' ');
  }

}

function addClass(ele, cls) {
  if (!hasClass(ele, cls)) {
    ele.className = ele.className === '' ? cls : ele.className + ' ' + cls;
  }
}

function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    var newClass = ' ' + ele.className.replace(/[\t\r\n]/g, '') + ' ';
    while (newClass.indexOf(' ' + cls + ' ') >= 0) {
      newClass = newClass.replace(' ' + cls + ' ', ' ');
    }
    ele.className = newClass.replace(/^\s+|\s+$/g, '');
  }
}

// 过滤出包含a的子节点，然后用过滤出的节点增加class
// function getHeadlineA(ele,clsName){
//     var childNodes = ele.children;   //HTMLCollection
//     for (let i = 0; i < childNodes.length; i++) {
//       if (childNodes[i].tagName.toLowerCase()==='a'){
//         addClass(childNodes[i], clsName);
//       }
//     }
// }

<|endoftext|>