<commit_before>import * as utils from 'base/utils';
import Hook from 'models/hook';

/*!
 * VIZABI Color Model (hook)
 */


var allowTypes = {
    "indicator": ["linear", "log", "genericLog", "time", "pow"],
    "property": ["ordinal"],
    "constant": ["ordinal"]
};

var defaultPalettes = {
  "_continuous": {
    "0": "#B4DE79",
    "50": "#E1CE00",
    "100": "#F77481"
  },
  "_discrete": {
    "0": "#bcfa83",
    "1": "#4cd843",
    "2": "#ff8684",
    "3": "#e83739",
    "4": "#ffb04b",
    "5": "#ff7f00",
    "6": "#f599f5",
    "7": "#c027d4",
    "8": "#f4f459",
    "9": "#d66425",
    "10": "#7fb5ed",
    "11": "#0ab8d8"
  },
  "_default": {
    "_default": "#93daec"
  }
};

var ColorModel = Hook.extend({

  /**
   * Default values for this model
   */
  _defaults: {
    use: "constant",
    which: "_default",
    scaleType: "ordinal",
    syncModels: [],
    palette: {},
    paletteLabels: null,
    allow: {
      //this is almost everything, but not "nominal", so no random strings like "name"
      scales: ["linear", "log", "genericLog", "time", "pow", "ordinal"]
    }
  },

  /**
   * Initializes the color hook
   * @param {Object} values The initial values of this model
   * @param parent A reference to the parent model
   * @param {Object} bind Initial events to bind
   */
  init: function(name, values, parent, bind) {
    var _this = this;
    this._type = "color";

    this._super(name, values, parent, bind);

    this._syncModelReferences = {};
    this._firstLoad = true;
    this._hasDefaultColor = false;

    this.on('hook_change', function() {
      if(_this._readyOnce) return;

      if(_this.palette && Object.keys(_this.palette._data).length!==0) {
        var defaultPalette = _this.getDefaultPalette();
        var currentPalette = _this.getPalette();
        var palette = {};
        //extend partial current palette with default palette and
        //switch current palette elements which equals
        //default palette elments to nonpersistent state
        Object.keys(defaultPalette).map(function(key) {
          if(!currentPalette[key]||defaultPalette[key]==currentPalette[key]) palette[key] = defaultPalette[key];
        });
        _this.set("palette", palette, false, false);
      }
    });
  },

  // args: {colorID, shadeID}
  getColorShade: function(args){
    var palette = this.getPalette();

    if(!args) return utils.warn("getColorShade() is missing arguments");

    // if colorID is not given or not found in the palette, replace it with default color
    if(!args.colorID || !palette[args.colorID]) args.colorID = "_default";

    // if the resolved colr value is not an array (has only one shade) -- return it
    if( !utils.isArray(palette[args.colorID]) ) return palette[args.colorID];

    var conceptpropsColor = this.getConceptprops().color;
    var shade = args.shadeID && conceptpropsColor && conceptpropsColor.shades && conceptpropsColor.shades[args.shadeID] ? conceptpropsColor.shades[args.shadeID] : 0;

    return palette[args.colorID][shade];

  },

  /**
   * Get the above constants
   */
  isUserSelectable: function() {
    var conceptpropsColor = this.getConceptprops().color;
    return conceptpropsColor == null || conceptpropsColor.selectable == null || conceptpropsColor.selectable;
  },

  whichChange: function(newValue) {
    this._super(newValue);
    if(this.palette) this.palette._data = {};
    this._setSyncModels();
  },

  /**
   * Validates a color hook
   */
  validate: function() {
    var _this = this;
    
    //only some scaleTypes are allowed depending on use. reset to default if inappropriate
    if(allowTypes[this.use].indexOf(this.scaleType) === -1) this.scaleType = allowTypes[this.use][0];

    // if there are models to sync: do it on first load or on changing the which
    if(this._firstLoad) {
      _this._setSyncModels();
    }

    this._firstLoad = false;
  },

  _setSyncModels: function() {
    var _this = this;
    this.syncModels.forEach(function(modelName){
      //fetch the model to sync, it's marker and entities
      var model = _this.getClosestModel(modelName);
      var marker = model.isHook()? model._parent : model;
      var entities = marker.getClosestModel(marker.space[0]);

      //save the references here locally
      _this._syncModelReferences[modelName] = {model: model, marker: marker, entities: entities};

      if(_this.use === "property") _this._setSyncModel(model, marker, entities);
    });
  },

  _setSyncModel: function(model, marker, entities) {
    if(model == marker){
      /*TODO: when WS will learn to respond correctly to the queries
      outside the same entity domain this can be reduced to<commit_msg>Remove syncmodels from color validation<commit_after>import * as utils from 'base/utils';
import Hook from 'models/hook';

/*!
 * VIZABI Color Model (hook)
 */


var allowTypes = {
    "indicator": ["linear", "log", "genericLog", "time", "pow"],
    "property": ["ordinal"],
    "constant": ["ordinal"]
};

var defaultPalettes = {
  "_continuous": {
    "0": "#B4DE79",
    "50": "#E1CE00",
    "100": "#F77481"
  },
  "_discrete": {
    "0": "#bcfa83",
    "1": "#4cd843",
    "2": "#ff8684",
    "3": "#e83739",
    "4": "#ffb04b",
    "5": "#ff7f00",
    "6": "#f599f5",
    "7": "#c027d4",
    "8": "#f4f459",
    "9": "#d66425",
    "10": "#7fb5ed",
    "11": "#0ab8d8"
  },
  "_default": {
    "_default": "#93daec"
  }
};

var ColorModel = Hook.extend({

  /**
   * Default values for this model
   */
  _defaults: {
    use: "constant",
    which: "_default",
    scaleType: "ordinal",
    syncModels: [],
    palette: {},
    paletteLabels: null,
    allow: {
      //this is almost everything, but not "nominal", so no random strings like "name"
      scales: ["linear", "log", "genericLog", "time", "pow", "ordinal"]
    }
  },

  /**
   * Initializes the color hook
   * @param {Object} values The initial values of this model
   * @param parent A reference to the parent model
   * @param {Object} bind Initial events to bind
   */
  init: function(name, values, parent, bind) {
    var _this = this;
    this._type = "color";

    this._super(name, values, parent, bind);

    this._syncModelReferences = {};
    this._hasDefaultColor = false;

    this.on('hook_change', function() {
      if(_this._readyOnce) return;

      if(_this.palette && Object.keys(_this.palette._data).length!==0) {
        var defaultPalette = _this.getDefaultPalette();
        var currentPalette = _this.getPalette();
        var palette = {};
        //extend partial current palette with default palette and
        //switch current palette elements which equals
        //default palette elments to nonpersistent state
        Object.keys(defaultPalette).map(function(key) {
          if(!currentPalette[key]||defaultPalette[key]==currentPalette[key]) palette[key] = defaultPalette[key];
        });
        _this.set("palette", palette, false, false);
      }
    });
  },

  setInterModelListeners: function () {
    this._super();
    this._setSyncModels();
  },

  // args: {colorID, shadeID}
  getColorShade: function(args){
    var palette = this.getPalette();

    if(!args) return utils.warn("getColorShade() is missing arguments");

    // if colorID is not given or not found in the palette, replace it with default color
    if(!args.colorID || !palette[args.colorID]) args.colorID = "_default";

    // if the resolved colr value is not an array (has only one shade) -- return it
    if( !utils.isArray(palette[args.colorID]) ) return palette[args.colorID];

    var conceptpropsColor = this.getConceptprops().color;
    var shade = args.shadeID && conceptpropsColor && conceptpropsColor.shades && conceptpropsColor.shades[args.shadeID] ? conceptpropsColor.shades[args.shadeID] : 0;

    return palette[args.colorID][shade];

  },

  /**
   * Get the above constants
   */
  isUserSelectable: function() {
    var conceptpropsColor = this.getConceptprops().color;
    return conceptpropsColor == null || conceptpropsColor.selectable == null || conceptpropsColor.selectable;
  },

  whichChange: function(newValue) {
    this._super(newValue);
    if(this.palette) this.palette._data = {};
    this._setSyncModels();
  },

  /**
   * Validates a color hook
   */
  validate: function() {    
    //only some scaleTypes are allowed depending on use. reset to default if inappropriate
    if(allowTypes[this.use].indexOf(this.scaleType) === -1) this.scaleType = allowTypes[this.use][0];

  },

  _setSyncModels: function() {
    var _this = this;
    this.syncModels.forEach(function(modelName){
      //fetch the model to sync, it's marker and entities
      var model = _this.getClosestModel(modelName);
      var marker = model.isHook()? model._parent : model;
      var entities = marker.getClosestModel(marker.space[0]);

      //save the references here locally
      _this._syncModelReferences[modelName] = {model: model, marker: marker, entities: entities};

      if(_this.use === "property") _this._setSyncModel(model, marker, entities);
    });
  },

  _setSyncModel: function(model, marker, entities) {
    if(model == marker){
      /*TODO: when WS will learn to respond correctly to the queries
      outside the same entity domain this can be reduced to
{'fraction_non_alphanumeric': 0.14671564390665515, 'fraction_numerical': 0.01728608470181504, 'mean_word_length': 3.16981981981982, 'pattern_counts': {'":': 44, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3699839', 'n_tokens_mistral': 3020, 'n_tokens_neox': 2888, 'n_words': 770}