<commit_before>(function () {
  'use strict';

  angular
    .module('app')
    .factory('StratSectionFactory', StratSectionFactory);

  StratSectionFactory.$inject = ['$ionicPopup', '$log', '$q', 'DataModelsFactory', 'HelpersFactory', 'MapLayerFactory',
    'MapSetupFactory', 'SpotFactory'];

  function StratSectionFactory($ionicPopup, $log, $q, DataModelsFactory, HelpersFactory, MapLayerFactory,
                               MapSetupFactory, SpotFactory) {
    var basicLitholigiesLabels = ['other', 'coal', 'mudstone', 'sandstone', 'conglomerate/breccia', 'limestone/dolostone'];
    var grainSizeOptions = DataModelsFactory.getSedLabelsDictionary();
    var spotsWithStratSections = {};
    var stratSectionSpots = {};
    var xInterval = 10;  // Horizontal spacing between grain sizes/weathering tick marks
    var yMultiplier = 20;  // 1 m interval thickness = 20 pixels

    return {
      'changedColumnProfile': changedColumnProfile,
      'checkForIntervalUpdates': checkForIntervalUpdates,
      'createInterval': createInterval,
      'deleteInterval': deleteInterval,
      'doUnitsFieldsMatch': doUnitsFieldsMatch,
      'drawAxes': drawAxes,
      'extractAddIntervalData': extractAddIntervalData,
      'gatherSpotsWithStratSections': gatherSpotsWithStratSections,
      'gatherStratSectionSpots': gatherStratSectionSpots,
      'getSpotWithThisStratSection': getSpotWithThisStratSection,
      'getSpotsWithStratSections': getSpotsWithStratSections,
      'getStratSectionIntervals': getStratSectionIntervals,
      'getStratSectionSettings': getStratSectionSettings,
      'getStratSectionSpots': getStratSectionSpots,
      'isMappedInterval': isMappedInterval,
      'isInterval': isInterval,
      'moveIntervalToAfter': moveIntervalToAfter,
      'orderStratSectionIntervals': orderStratSectionIntervals,
      'getDefaultUnits': getDefaultUnits,
      'validateNewInterval': validateNewInterval
    };

    /**
     * Private Functions
     */

    // Calculate the geometry for an interval (single bed or interbedded)
    function calculateIntervalGeometry(stratSectionId, sedData, minY) {
      var character = sedData.character;
      var interval = sedData.interval;
      var bedding = sedData.bedding;

      var intervalHeight = interval.interval_thickness * yMultiplier;
      var intervalWidth = getIntervalWidth(sedData, stratSectionId);
      var minX = 0;
      var maxX = minX + intervalWidth;
      var maxY = minY + intervalHeight;

      var geometry = {};
      geometry = {
        'type': 'Polygon',
        'coordinates': [[[minX, minY], [minX, maxY], [maxX, maxY], [maxX, minY], [minX, minY]]]
      };

      // If interbedded need to create a geometry collection with polygons for each bed
      if ((character === 'interbedded' || character === 'bed_mixed_lit') && bedding && bedding.beds &&
        bedding.beds[1] && (bedding.beds[1].avg_thickness && bedding.beds[1].avg_thickness > 0 ||
          (bedding.beds[1].max_thickness && bedding.beds[1].max_thickness > 0 && bedding.beds[1].min_thickness &&
            bedding.beds[1].min_thickness > 0)) && bedding.interbed_proportion > 0) {
        var thickness = bedding.beds[1].avg_thickness ? bedding.beds[1].avg_thickness : (bedding.beds[1].max_thickness + bedding.beds[1].min_thickness) / 2;

        // Per Casey: Don't use the data from Lithology 1 interbed thickness for plotting since it, along with interval
        // thickness, proportion and Lithology 2 interbed thickness are too many data numbers to plot all faithfully
        //var y2 = 0.0066 * thickness * thickness + 0.0637 * thickness + 0.1385;
        var y2 = thickness * yMultiplier < intervalHeight ? thickness * yMultiplier : intervalHeight;
        var interbedHeight2 = intervalHeight * (bedding.interbed_proportion / 100 || .5);  // secondary interbed
        interbedHeight2 = interbedHeight2 > y2 ? interbedHeight2 : y2;
        var interbedHeight1 = intervalHeight - interbedHeight2;                             // primary interbed

        var numInterbeds2 = interbedHeight2 / y2;
        var y1 = interbedHeight1 / numInterbeds2;

        var interbedIntervalWidth = getIntervalWidth(sedData, stratSectionId, true);
        var maxXBed = intervalWidth;
        var minYBed = angular.copy(minY);
        var maxYBed = angular.copy(minY);
        var currentBedHeight = y1;
        var polyCoords = [];
        while (maxYBed < minY + intervalHeight) {
          maxYBed = minYBed + currentBedHeight <= minY + intervalHeight ? minYBed + currentBedHeight : minY + intervalHeight;
          var coords = [[minX, minYBed], [minX, maxYBed], [maxXBed, maxYBed], [maxXBed, minYBed], [minX, minYBed]];
          polyCoords.push(coords);
          currentBedHeight = currentBedHeight === y1 ? y2 : y1;
          maxXBed = maxXBed === intervalWidth ? interbedIntervalWidth : intervalWidth;
          minYBed = angular.copy(maxYBed);
        }

        var geometries = [];
        _.each(polyCoords, function (polyCoord) {
          geometries.push({
            'type': 'Polygon',
            'coordinates': [polyCoord]
          });
        });

        geometry = {
          'type': 'GeometryCollection',
          'geometries': geometries
        };
      }
      else if (character === 'interbedded' || character === 'bed_mixed_lit') {
        $log.log('Not enough data to properly draw interval', sedData);
        $ionicPopup.alert({
          'title': 'Data Error!',
          'template': 'Not enough data to properly draw this interval.'
        });
      }
      return geometry;
    }

    // X-Axis
    function drawAxisX(ctx, pixelRatio, yAxisHeight, labels, spacing, color) {
      var p = getPixel([-10, 0], pixelRatio);
      ctx.moveTo(p.x, p.y);
      var xAxisLength = (_.size(labels) + 1) * xInterval;
      p = getPixel([xAxisLength, 0], pixelRatio);
      ctx.lineTo(p.x, p.y);
      ctx.stroke();

      // Create Grain Size Labels for X Axis
      ctx.textAlign = "right";
      ctx.lineWidth = 3;<commit_msg>Sed: Updated error message when not enough data to draw interbedded or mixed interval<commit_after>(function () {
  'use strict';

  angular
    .module('app')
    .factory('StratSectionFactory', StratSectionFactory);

  StratSectionFactory.$inject = ['$ionicPopup', '$log', '$q', 'DataModelsFactory', 'HelpersFactory', 'MapLayerFactory',
    'MapSetupFactory', 'SpotFactory'];

  function StratSectionFactory($ionicPopup, $log, $q, DataModelsFactory, HelpersFactory, MapLayerFactory,
                               MapSetupFactory, SpotFactory) {
    var basicLitholigiesLabels = ['other', 'coal', 'mudstone', 'sandstone', 'conglomerate/breccia', 'limestone/dolostone'];
    var grainSizeOptions = DataModelsFactory.getSedLabelsDictionary();
    var spotsWithStratSections = {};
    var stratSectionSpots = {};
    var xInterval = 10;  // Horizontal spacing between grain sizes/weathering tick marks
    var yMultiplier = 20;  // 1 m interval thickness = 20 pixels

    return {
      'changedColumnProfile': changedColumnProfile,
      'checkForIntervalUpdates': checkForIntervalUpdates,
      'createInterval': createInterval,
      'deleteInterval': deleteInterval,
      'doUnitsFieldsMatch': doUnitsFieldsMatch,
      'drawAxes': drawAxes,
      'extractAddIntervalData': extractAddIntervalData,
      'gatherSpotsWithStratSections': gatherSpotsWithStratSections,
      'gatherStratSectionSpots': gatherStratSectionSpots,
      'getSpotWithThisStratSection': getSpotWithThisStratSection,
      'getSpotsWithStratSections': getSpotsWithStratSections,
      'getStratSectionIntervals': getStratSectionIntervals,
      'getStratSectionSettings': getStratSectionSettings,
      'getStratSectionSpots': getStratSectionSpots,
      'isMappedInterval': isMappedInterval,
      'isInterval': isInterval,
      'moveIntervalToAfter': moveIntervalToAfter,
      'orderStratSectionIntervals': orderStratSectionIntervals,
      'getDefaultUnits': getDefaultUnits,
      'validateNewInterval': validateNewInterval
    };

    /**
     * Private Functions
     */

    // Calculate the geometry for an interval (single bed or interbedded)
    function calculateIntervalGeometry(stratSectionId, sedData, minY) {
      var character = sedData.character;
      var interval = sedData.interval;
      var bedding = sedData.bedding;

      var intervalHeight = interval.interval_thickness * yMultiplier;
      var intervalWidth = getIntervalWidth(sedData, stratSectionId);
      var minX = 0;
      var maxX = minX + intervalWidth;
      var maxY = minY + intervalHeight;

      var geometry = {};
      geometry = {
        'type': 'Polygon',
        'coordinates': [[[minX, minY], [minX, maxY], [maxX, maxY], [maxX, minY], [minX, minY]]]
      };

      // If interbedded need to create a geometry collection with polygons for each bed
      if ((character === 'interbedded' || character === 'bed_mixed_lit') && bedding && bedding.beds &&
        bedding.beds[1] && (bedding.beds[1].avg_thickness && bedding.beds[1].avg_thickness > 0 ||
          (bedding.beds[1].max_thickness && bedding.beds[1].max_thickness > 0 && bedding.beds[1].min_thickness &&
            bedding.beds[1].min_thickness > 0)) && bedding.interbed_proportion > 0) {
        var thickness = bedding.beds[1].avg_thickness ? bedding.beds[1].avg_thickness : (bedding.beds[1].max_thickness + bedding.beds[1].min_thickness) / 2;

        // Per Casey: Don't use the data from Lithology 1 interbed thickness for plotting since it, along with interval
        // thickness, proportion and Lithology 2 interbed thickness are too many data numbers to plot all faithfully
        //var y2 = 0.0066 * thickness * thickness + 0.0637 * thickness + 0.1385;
        var y2 = thickness * yMultiplier < intervalHeight ? thickness * yMultiplier : intervalHeight;
        var interbedHeight2 = intervalHeight * (bedding.interbed_proportion / 100 || .5);  // secondary interbed
        interbedHeight2 = interbedHeight2 > y2 ? interbedHeight2 : y2;
        var interbedHeight1 = intervalHeight - interbedHeight2;                             // primary interbed

        var numInterbeds2 = interbedHeight2 / y2;
        var y1 = interbedHeight1 / numInterbeds2;

        var interbedIntervalWidth = getIntervalWidth(sedData, stratSectionId, true);
        var maxXBed = intervalWidth;
        var minYBed = angular.copy(minY);
        var maxYBed = angular.copy(minY);
        var currentBedHeight = y1;
        var polyCoords = [];
        while (maxYBed < minY + intervalHeight) {
          maxYBed = minYBed + currentBedHeight <= minY + intervalHeight ? minYBed + currentBedHeight : minY + intervalHeight;
          var coords = [[minX, minYBed], [minX, maxYBed], [maxXBed, maxYBed], [maxXBed, minYBed], [minX, minYBed]];
          polyCoords.push(coords);
          currentBedHeight = currentBedHeight === y1 ? y2 : y1;
          maxXBed = maxXBed === intervalWidth ? interbedIntervalWidth : intervalWidth;
          minYBed = angular.copy(maxYBed);
        }

        var geometries = [];
        _.each(polyCoords, function (polyCoord) {
          geometries.push({
            'type': 'Polygon',
            'coordinates': [polyCoord]
          });
        });

        geometry = {
          'type': 'GeometryCollection',
          'geometries': geometries
        };
      }
      else if (character === 'interbedded' || character === 'bed_mixed_lit') {
        $log.log('Not enough data to properly draw interval', sedData);
        $ionicPopup.alert({
          'title': 'Data Error!',
          'template': 'This interval is <b>interbedded</b> or <b>mixed</b> but there is not enough data to properly ' +
            'draw this interval. Check that you have entered all of the necessary bedding data for two lithologies. ' +
            'This includes the <b>Lithology 1: Interbed Relative Proportion (%)</b> and either the <b>Average ' +
            'Thickness</b> or both the <b>Maximum Thickness</b> and <b>Minimum Thickness</b> of the interbeds for ' +
            'both lithologies found on the <b>Bedding</b> page. '
        });
      }
      return geometry;
    }

    // X-Axis
    function drawAxisX(ctx, pixelRatio, yAxisHeight, labels, spacing, color) {
      var p = getPixel([-10, 0], pixelRatio);
      ctx.moveTo(p.x, p.y);
      var xAxisLength = (_.size(labels) + 1) * xInterval;
      p = getPixel([xAxisLength, 0], pixelRatio);
      ctx.lineTo(p.x, p.y);
      ctx.stroke();

      // Create Grain Size Labels for X Axis
      ctx.textAlign = "right";
      ctx.lineWidth = 3;
{'fraction_non_alphanumeric': 0.11132345914954611, 'fraction_numerical': 0.011387163561076604, 'mean_word_length': 3.035668380462725, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 27, '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': '1686849', 'n_tokens_mistral': 3878, 'n_tokens_neox': 3659, 'n_words': 898}