<commit_before>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ExperimentListController',
    [
        '$scope',
        '$q',
        'ImagesetSubregionCount',
        function ($scope, $q, ImagesetSubregionCount) {
            var image_set_counts = ImagesetSubregionCount.query({});

            image_set_counts.$promise.then(function(results) {
                $scope.imagesetscounts = [];
                results.forEach(function(result) {
                    var temp = {};
                    temp['imageset_name'] = result['imageset_name'];
                    temp['image_set_id'] = result['imageset_id'];
                    var image_count = 0;
                    var image_subregion_count = 0;
                    var subregion_count=0;
                    result['images'].forEach(function(image) {
                        image_count += 1;
                        if (image.subregion_count>0) {
                            image_subregion_count+=1;
                            subregion_count+=image.subregion_count
                        }
                    });
                    temp['image_count'] = image_count;
                    temp['image_subregion_count'] = image_subregion_count;
                    temp['subregion_count'] = subregion_count;
                    $scope.imagesetscounts.push(temp);
                })
            });
        }
    ]
);

app.controller(
    'ExperimentDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$window',
        'ImageSet',
        'Image',
        'Subregion',
        'ExperimentProbe',
        'AnatomyByProbe',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $window, ImageSet, Image,
                  Subregion, ExperimentProbe, AnatomyByProbe, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'view';  // can be 'view', 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            var imageset = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            imageset.$promise.then(function(data) {
                $scope.anatomies = [];
                $scope.animageset = data;
                data.probes.forEach(function(probe) {
                    $scope.anatomies.push(AnatomyByProbe.get(
                        {
                            'probe_id': probe.probe
                        }).$promise
                    );
                });

                $q.all($scope.anatomies).then(function (results) {
                    $scope.anatomies_now = [];
                    results.forEach(function(exp) {
                        $scope.anatomies_now.push.apply($scope.anatomies_now, exp.anatomies);
                    });

                    }, function(reason) {
                        // Error callback where reason is the value of the first rejected promise
                        $window.alert(JSON.stringify(reason, null, 4));
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data
                    }, function (error) {
                        // TODO: figure out how to turn retrieving off for experiment
                        $window.alert(JSON.stringify(error, null, 4))
                    });
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.anatomy_id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length === 0) {
                    $window.alert('There are no regions drawn, please segment something first.');
                } else if ($scope.selected_classification === null) {
                    $window.alert('There is no label associated with the active polygon, please choose a label first.');
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.anatomy_id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                        }
                    }, function (error) {
                        $window.alert(JSON.stringify(error.data, null, 4))
                    });
                }
            };

            $scope.train_model = function () {
                TrainModel.save(
                    {
                        'imageset': imageset.id
                    }
                );
            };

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    console.log(results);
                    $window.alert(JSON.stringify(results, null, 4));
                });
            }
        }
    ]
);
<commit_msg>add Species to ExperimentListController<commit_after>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ExperimentListController',
    [
        '$scope',
        '$q',
        'ImagesetSubregionCount',
        'Species',
        function ($scope, $q, ImagesetSubregionCount, Species) {
            $scope.species = Species.query();

            var image_set_counts = ImagesetSubregionCount.query({});

            image_set_counts.$promise.then(function(results) {
                $scope.imagesetscounts = [];
                results.forEach(function(result) {
                    var temp = {};
                    temp['imageset_name'] = result['imageset_name'];
                    temp['image_set_id'] = result['imageset_id'];
                    var image_count = 0;
                    var image_subregion_count = 0;
                    var subregion_count=0;
                    result['images'].forEach(function(image) {
                        image_count += 1;
                        if (image.subregion_count>0) {
                            image_subregion_count+=1;
                            subregion_count+=image.subregion_count
                        }
                    });
                    temp['image_count'] = image_count;
                    temp['image_subregion_count'] = image_subregion_count;
                    temp['subregion_count'] = subregion_count;
                    $scope.imagesetscounts.push(temp);
                })
            });
        }
    ]
);

app.controller(
    'ExperimentDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$window',
        'ImageSet',
        'Image',
        'Subregion',
        'ExperimentProbe',
        'AnatomyByProbe',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $window, ImageSet, Image,
                  Subregion, ExperimentProbe, AnatomyByProbe, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'view';  // can be 'view', 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            var imageset = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            imageset.$promise.then(function(data) {
                $scope.anatomies = [];
                $scope.animageset = data;
                data.probes.forEach(function(probe) {
                    $scope.anatomies.push(AnatomyByProbe.get(
                        {
                            'probe_id': probe.probe
                        }).$promise
                    );
                });

                $q.all($scope.anatomies).then(function (results) {
                    $scope.anatomies_now = [];
                    results.forEach(function(exp) {
                        $scope.anatomies_now.push.apply($scope.anatomies_now, exp.anatomies);
                    });

                    }, function(reason) {
                        // Error callback where reason is the value of the first rejected promise
                        $window.alert(JSON.stringify(reason, null, 4));
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data
                    }, function (error) {
                        // TODO: figure out how to turn retrieving off for experiment
                        $window.alert(JSON.stringify(error, null, 4))
                    });
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.anatomy_id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length === 0) {
                    $window.alert('There are no regions drawn, please segment something first.');
                } else if ($scope.selected_classification === null) {
                    $window.alert('There is no label associated with the active polygon, please choose a label first.');
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.anatomy_id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                        }
                    }, function (error) {
                        $window.alert(JSON.stringify(error.data, null, 4))
                    });
                }
            };

            $scope.train_model = function () {
                TrainModel.save(
                    {
                        'imageset': imageset.id
                    }
                );
            };

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    console.log(results);
                    $window.alert(JSON.stringify(results, null, 4));
                });
            }
        }
    ]
);
<|endoftext|>


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

'use strict';

const fs = require('fs');
const spawn = require('child_process').spawn;

const supportedPlatforms = ['android', 'ios'];
const envVariables = {
  enableAutoconfigure: 'ONEGINI_AUTOCONFIGURE',
  configuratorName: 'ONEGINI_SDK_CONFIGURATOR',
  configFiles: {
    android: 'ONEGINI_CONFIG_ANDROID',
    ios: 'ONEGINI_CONFIG_IOS'
  }
};

module.exports = function (context) {
  if (process.env.ONEGINI_AUTOCONFIGURE === "false") {
    console.log('ONEGINI_AUTOCONFIGURE is set to false. Skipping Onegini SDK Configuration');
    return;
  }

  const deferral = context.requireCordovaModule('q').defer();
  const args = [
    '--cordova',
    '--app-dir', context.opts.projectRoot
  ];
  console.log('Configuring the Onegini SDK');
  console.log('===========================\n\n');

  context.opts.platforms.forEach((platform) => {
    if (arrayContains(platform, supportedPlatforms)) {
      let platformArgs = args;

      console.log(`Configuring the ${platform} platform`);
      console.log('--------------------------' + new Array(platform.length).join('-') + '\n');

      platformArgs.unshift(platform);
      platformArgs.push('--config', getConfigFileForPlatform(context.opts.projectRoot, platform));

      execConfigurator(platformArgs, deferral);
    } else {
      console.log(`Skipping unsupported platform: ${platform}`)
    }
  });

  return deferral.promise;
};

function execConfigurator(args, deferral) {
  const configuratorName = getConfiguratorName();

  console.log('\nRunning command:');
  console.log(`${configuratorName} ${args.join(' ')}\n`);

  const configurator = spawn(configuratorName, args);

  configurator.stdout.on('data', (data) => {
    process.stdout.write(data);
  });

  configurator.stderr.on('data', (data) => {
    process.stdout.write(data);
  });

  configurator.on('close', (code) => {
    if (code === 0) {
      deferral.resolve();
    } else {
      deferral.reject('Could not configure the Onegini SDK with your configuration');
    }
  });
}

function getConfigFileForPlatform(projectRoot, platform) {
  const environmentVar = envVariables.configFiles[platform];
  const environmentLocation = process.env[environmentVar];
  const defaultLocation = `${projectRoot}/onegini-config-${platform}.zip`;

  if (environmentLocation) {
    console.log(`Using Token Server config zip: '${environmentLocation}' set in ${environmentVar}`);
    return environmentLocation;
  }

  console.log(`Using default Token Server config zip: '${defaultLocation}'`);
  return defaultLocation;
}

function getConfiguratorName() {
  const environmentVar = envVariables.configuratorName;
  const environmentName = process.env[environmentVar];
  const defaultName = 'onegini-sdk-configurator';

  if (environmentName) {
    console.log(`Using SDK Configurator executable in '${environmentName}' set in ${environmentVar}`);
    return environmentName;
  }

  console.log('Using SDK Configurator from $PATH');
  return defaultName;
}

function arrayContains(needle, arrhaystack) {
  return (arrhaystack.indexOf(needle) > -1);
}<commit_msg>CORDOPLUG-199 Rename env variables in configurator hook.<commit_after>/*
 * Copyright (c) 2016 Onegini B.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const fs = require('fs');
const spawn = require('child_process').spawn;

const supportedPlatforms = ['android', 'ios'];
const envVariables = {
  enableAutoconfigure: 'ONEGINI_AUTOCONFIGURE',
  configuratorName: 'ONEGINI_SDK_CONFIGURATOR_PATH',
  configFiles: {
    android: 'ONEGINI_CONFIG_ANDROID_PATH',
    ios: 'ONEGINI_CONFIG_IOS_PATH'
  }
};

module.exports = function (context) {
  if (process.env.ONEGINI_AUTOCONFIGURE === "false") {
    console.log('ONEGINI_AUTOCONFIGURE is set to false. Skipping Onegini SDK Configuration');
    return;
  }

  const deferral = context.requireCordovaModule('q').defer();
  const args = [
    '--cordova',
    '--app-dir', context.opts.projectRoot
  ];
  console.log('Configuring the Onegini SDK');
  console.log('===========================\n\n');

  context.opts.platforms.forEach((platform) => {
    if (arrayContains(platform, supportedPlatforms)) {
      let platformArgs = args;

      console.log(`Configuring the ${platform} platform`);
      console.log('--------------------------' + new Array(platform.length).join('-') + '\n');

      platformArgs.unshift(platform);
      platformArgs.push('--config', getConfigFileForPlatform(context.opts.projectRoot, platform));

      execConfigurator(platformArgs, deferral);
    } else {
      console.log(`Skipping unsupported platform: ${platform}`)
    }
  });

  return deferral.promise;
};

function execConfigurator(args, deferral) {
  const configuratorName = getConfiguratorName();

  console.log('\nRunning command:');
  console.log(`${configuratorName} ${args.join(' ')}\n`);

  const configurator = spawn(configuratorName, args);

  configurator.stdout.on('data', (data) => {
    process.stdout.write(data);
  });

  configurator.stderr.on('data', (data) => {
    process.stdout.write(data);
  });

  configurator.on('close', (code) => {
    if (code === 0) {
      deferral.resolve();
    } else {
      deferral.reject('Could not configure the Onegini SDK with your configuration');
    }
  });
}

function getConfigFileForPlatform(projectRoot, platform) {
  const environmentVar = envVariables.configFiles[platform];
  const environmentLocation = process.env[environmentVar];
  const defaultLocation = `${projectRoot}/onegini-config-${platform}.zip`;

  if (environmentLocation) {
    console.log(`Using Token Server config zip: '${environmentLocation}' set in ${environmentVar}`);
    return environmentLocation;
  }

  console.log(`Using default Token Server config zip: '${defaultLocation}'`);
  return defaultLocation;
}

function getConfiguratorName() {
  const environmentVar = envVariables.configuratorName;
  const environmentName = process.env[environmentVar];
  const defaultName = 'onegini-sdk-configurator';

  if (environmentName) {
    console.log(`Using SDK Configurator executable in '${environmentName}' set in ${environmentVar}`);
    return environmentName;
  }

  console.log('Using SDK Configurator from $PATH');
  return defaultName;
}

function arrayContains(needle, arrhaystack) {
  return (arrhaystack.indexOf(needle) > -1);
}<|endoftext|>


<commit_before>#!/usr/bin/env node

module.exports = function(context) {

    /** @external */
    var fs = context.requireCordovaModule('fs'),
        path = context.requireCordovaModule('path'),
        ConfigParser = context.requireCordovaModule("cordova-lib/src/configparser/ConfigParser"),
        XmlHelpers = context.requireCordovaModule("cordova-lib/src/util/xml-helpers"),
        et = context.requireCordovaModule('elementtree');

    /** @defaults */
    var xwalkVariables = {},
        argumentsString = context.cmdLine,
        pluginConfigurationFile = path.join(context.opts.plugin.dir, 'plugin.xml'),
        androidPlatformDir = path.join(context.opts.projectRoot,
            'platforms', 'android'),
        projectConfigurationFile = path.join(context.opts.projectRoot,
            'config.xml'),
        projectManifestFile = path.join(androidPlatformDir,
            'AndroidManifest.xml');

    /** Init */
    var CordovaConfig = new ConfigParser(projectConfigurationFile);

    var addPermission = function() {
        var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
        var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
        XmlHelpers.graftXML(projectManifestXmlRoot, [child], '/manifest');
        fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
    }

    var removePermission = function() {
        var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
        var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
        XmlHelpers.pruneXML(projectManifestXmlRoot, [child], '/manifest');
        fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
    }

    var defaultPreferences = function() {
        var pluginPreferences = {};

        var pluginXmlRoot = XmlHelpers.parseElementtreeSync(pluginConfigurationFile),
            tagName = "preference",
            containerName = "config-file",
            targetPlatform = 'android',
            targetPlatformTag = pluginXmlRoot.find('./platform[@name="' + targetPlatform + '"]');

        var tagsInRoot = pluginXmlRoot.findall(tagName) || [],
            tagsInPlatform = targetPlatformTag ? targetPlatformTag.findall(tagName) : [],
            tagsInContainer = targetPlatformTag ? targetPlatformTag.findall(containerName) : [],
            tagsList = tagsInRoot.concat(tagsInContainer);

        // Parses <preference> tags within <config-file>-blocks
        tagsList.map(function(prefTag) {
            prefTag.getchildren().forEach(function(element) {
                if ((element.tag == 'preference') && (element.attrib['name']) && element.attrib['default']) {
                    pluginPreferences[element.attrib['name']] = element.attrib['default'];
                }
            });
        });

        return pluginPreferences;
    }

    /** The style of name align with config.xml */
    var setConfigPreference = function(name, value) {
        var trimName = name.replace('_', '');
        for (localName in xwalkVariables) {
            if (localName.toUpperCase() == trimName.toUpperCase()) {
                xwalkVariables[localName] = value;
            }
        }
    }

    /** Pase the cli command to get the specific preferece*/
    var parseCliPreference = function() {
        var commandlineVariablesList = argumentsString.split('variable');
        if (commandlineVariablesList) {
            commandlineVariablesList.forEach(function(element) {
                var spaceList = element.split(' ');
                if (spaceList) {
                    spaceList.forEach(function(element) {
                        var preference = element.split('=');
                        if (preference && preference.length == 2) {
                            setConfigPreference(preference[0], preference[1]);
                        }
                    });
                }
            });
        }
    }

    /** Add preference */
    this.addPreferences = function() {
        // Pick the xwalk variables with the cli preferences
        parseCliPreference();

        // Add the permission of writing external storage when using shared mode
        if (xwalkVariables['xwalkMode'] == 'shared') {
            addPermission();
        }

        // Configure the final value in the config.xml
        var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
        var preferenceUpdated = false;
        for (name in xwalkVariables) {
            var child = configXmlRoot.find('./preference[@name="' + name + '"]');
            if(!child) {
                preferenceUpdated = true;
                child = et.XML('<preference name="' + name + '" value="' + xwalkVariables[name] + '" />');
                XmlHelpers.graftXML(configXmlRoot, [child], '/*');
            }
        }
        if(preferenceUpdated) {
            fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
        }
    }

    /** Remove preference*/
    this.removePreferences = function() {
        if (CordovaConfig.getGlobalPreference('xwalkMode') == 'shared') {
            // Add the permission of write_external_storage in shared mode
            removePermission();
        }

        var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
        for (name in xwalkVariables) {
            var child = configXmlRoot.find('./preference[@name="' + name + '"]');
            if (child) {
                XmlHelpers.pruneXML(configXmlRoot, [child], '/*');
            }
        }
        fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
    }

    xwalkVariables = defaultPreferences();

};<commit_msg>Prevent hooks failures in newest cordova versions<commit_after>#!/usr/bin/env node

module.exports = function(context) {

    var ConfigParser, XmlHelpers;
    try {
        ConfigParser = context.requireCordovaModule("cordova-lib/src/configparser/ConfigParser");
        XmlHelpers = context.requireCordovaModule("cordova-lib/src/util/xml-helpers");
    } catch (e) {
        // cordova-lib >= 5.3.4 doesn't contain ConfigParser and xml-helpers anymore
        ConfigParser = context.requireCordovaModule("cordova-common").ConfigParser;
        XmlHelpers = context.requireCordovaModule("cordova-common").xmlHelpers;
    }

    /** @external */
    var fs = context.requireCordovaModule('fs'),
        path = context.requireCordovaModule('path'),
        et = context.requireCordovaModule('elementtree');

    /** @defaults */
    var xwalkVariables = {},
        argumentsString = context.cmdLine,
        pluginConfigurationFile = path.join(context.opts.plugin.dir, 'plugin.xml'),
        androidPlatformDir = path.join(context.opts.projectRoot,
            'platforms', 'android'),
        projectConfigurationFile = path.join(context.opts.projectRoot,
            'config.xml'),
        projectManifestFile = path.join(androidPlatformDir,
            'AndroidManifest.xml');

    /** Init */
    var CordovaConfig = new ConfigParser(projectConfigurationFile);

    var addPermission = function() {
        var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
        var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
        XmlHelpers.graftXML(projectManifestXmlRoot, [child], '/manifest');
        fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
    }

    var removePermission = function() {
        var projectManifestXmlRoot = XmlHelpers.parseElementtreeSync(projectManifestFile);
        var child = et.XML('<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />');
        XmlHelpers.pruneXML(projectManifestXmlRoot, [child], '/manifest');
        fs.writeFileSync(projectManifestFile, projectManifestXmlRoot.write({indent: 4}), 'utf-8');
    }

    var defaultPreferences = function() {
        var pluginPreferences = {};

        var pluginXmlRoot = XmlHelpers.parseElementtreeSync(pluginConfigurationFile),
            tagName = "preference",
            containerName = "config-file",
            targetPlatform = 'android',
            targetPlatformTag = pluginXmlRoot.find('./platform[@name="' + targetPlatform + '"]');

        var tagsInRoot = pluginXmlRoot.findall(tagName) || [],
            tagsInPlatform = targetPlatformTag ? targetPlatformTag.findall(tagName) : [],
            tagsInContainer = targetPlatformTag ? targetPlatformTag.findall(containerName) : [],
            tagsList = tagsInRoot.concat(tagsInContainer);

        // Parses <preference> tags within <config-file>-blocks
        tagsList.map(function(prefTag) {
            prefTag.getchildren().forEach(function(element) {
                if ((element.tag == 'preference') && (element.attrib['name']) && element.attrib['default']) {
                    pluginPreferences[element.attrib['name']] = element.attrib['default'];
                }
            });
        });

        return pluginPreferences;
    }

    /** The style of name align with config.xml */
    var setConfigPreference = function(name, value) {
        var trimName = name.replace('_', '');
        for (localName in xwalkVariables) {
            if (localName.toUpperCase() == trimName.toUpperCase()) {
                xwalkVariables[localName] = value;
            }
        }
    }

    /** Pase the cli command to get the specific preferece*/
    var parseCliPreference = function() {
        var commandlineVariablesList = argumentsString.split('variable');
        if (commandlineVariablesList) {
            commandlineVariablesList.forEach(function(element) {
                var spaceList = element.split(' ');
                if (spaceList) {
                    spaceList.forEach(function(element) {
                        var preference = element.split('=');
                        if (preference && preference.length == 2) {
                            setConfigPreference(preference[0], preference[1]);
                        }
                    });
                }
            });
        }
    }

    /** Add preference */
    this.addPreferences = function() {
        // Pick the xwalk variables with the cli preferences
        parseCliPreference();

        // Add the permission of writing external storage when using shared mode
        if (xwalkVariables['xwalkMode'] == 'shared') {
            addPermission();
        }

        // Configure the final value in the config.xml
        var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
        var preferenceUpdated = false;
        for (name in xwalkVariables) {
            var child = configXmlRoot.find('./preference[@name="' + name + '"]');
            if(!child) {
                preferenceUpdated = true;
                child = et.XML('<preference name="' + name + '" value="' + xwalkVariables[name] + '" />');
                XmlHelpers.graftXML(configXmlRoot, [child], '/*');
            }
        }
        if(preferenceUpdated) {
            fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
        }
    }

    /** Remove preference*/
    this.removePreferences = function() {
        if (CordovaConfig.getGlobalPreference('xwalkMode') == 'shared') {
            // Add the permission of write_external_storage in shared mode
            removePermission();
        }

        var configXmlRoot = XmlHelpers.parseElementtreeSync(projectConfigurationFile);
        for (name in xwalkVariables) {
            var child = configXmlRoot.find('./preference[@name="' + name + '"]');
            if (child) {
                XmlHelpers.pruneXML(configXmlRoot, [child], '/*');
            }
        }
        fs.writeFileSync(projectConfigurationFile, configXmlRoot.write({indent: 4}), 'utf-8');
    }

    xwalkVariables = defaultPreferences();

};
<|endoftext|>


<commit_before>$( document ).ready(function() {
    loadTable();
});

function loadTable() {
    $('#objecttable').html(
        '
' +
            '
Loading...
' +
        '
'
    );
    $("#progress").show();
    $.ajax({
        url: loadtable_url,
        success: function(data) {
            $('#objecttable').html(data);
            $(document).foundation();
            $(".alert-box").click(function(e){

                $(this).slideUp();
            });
        }
    }).fail( function(data) {
        //On error, refresh the page. This will redirect to login
        //if session is expired.
        location.reload();
    });
}

$('input[id=file]').change(function() {
    $('#filetmp').val($(this).val());
});

$('#create-pseudofolder').on('submit', function(event){
    event.preventDefault();
    $("#create-pseudofolder").hide();
    $("#progress").show();
    create_folder();

});

function addMessage(text, extra_tags) {
    if (extra_tags == 'success') {
        $("#messages").html(
            '
' +
                '
' +
                    '
' +
                '{% trans "Success." %} ' + text +
                '×' +
                '
' +
                '
' +
            '
'
            );
    } else if (extra_tags == 'error') {
        $("#messages").html(
            '
' +
                '
' +
                    '
' +
                '{% trans "Error." %} ' + text +
                '×' +
                '
' +
                '
' +
            '
'
        );
    }
}

$(document).ready(function() {
    $('#messages').ajaxComplete(function(e, xhr, settings) {
        var contentType = xhr.getResponseHeader("Content-Type");

        if (contentType == "application/javascript" || contentType == "application/json") {
            var json = $.parseJSON(xhr.responseText);

            $.each(json.django_messages, function (i, item) {
                addMessage(item.message, item.extra_tags);
            });
        }
    }).ajaxError(function(e, xhr, settings, exception) {
        addMessage("There was an error processing your request, please try again.", "error");
    });
});

function create_folder() {
    $.ajax({
        method: "POST",
        url: create_folder_url,
        data: $('#create-pseudofolder').serialize()
    }).done(function() {
        $('#pseudoContainer').foundation('reveal', 'close');
        loadTable();
        $("#create-pseudofolder").show();
        $("#progress").hide();
    }).always(function(data, textStatus, jqXHR) {

        var contentType = jqXHR.getResponseHeader("Content-Type");

        if (contentType == "application/javascript" || contentType == "application/json") {
            var json = $.parseJSON(jqXHR.responseText);

            $.each(json.django_messages, function (i, item) {
                addMessage(item.message, item.extra_tags);
            });
        }
    });
};<commit_msg>Removed django templating from javascript messaging rendering.<commit_after>$( document ).ready(function() {
    loadTable();
});

function loadTable() {
    $('#objecttable').html(
        '
' +
            '
Loading...
' +
        '
'
    );
    $("#progress").show();
    $.ajax({
        url: loadtable_url,
        success: function(data) {
            $('#objecttable').html(data);
            $(document).foundation();
            $(".alert-box").click(function(e){

                $(this).slideUp();
            });
        }
    }).fail( function(data) {
        //On error, refresh the page. This will redirect to login
        //if session is expired.
        location.reload();
    });
}

$('input[id=file]').change(function() {
    $('#filetmp').val($(this).val());
});

$('#create-pseudofolder').on('submit', function(event){
    event.preventDefault();
    $("#create-pseudofolder").hide();
    $("#progress").show();
    create_folder();

});

function addMessage(text, extra_tags) {
    if (extra_tags == 'success') {
        $("#messages").html(
            '
' +
                '
' +
                    '
' +
                'Success. ' + text +
                '×' +
                '
' +
                '
' +
            '
'
            );
    } else if (extra_tags == 'error') {
        $("#messages").html(
            '
' +
                '
' +
                    '
' +
                'Error. ' + text +
                '×' +
                '
' +
                '
' +
            '
'
        );
    }
}

$(document).ready(function() {
    $('#messages').ajaxComplete(function(e, xhr, settings) {
        var contentType = xhr.getResponseHeader("Content-Type");

        if (contentType == "application/javascript" || contentType == "application/json") {
            var json = $.parseJSON(xhr.responseText);

            $.each(json.django_messages, function (i, item) {
                addMessage(item.message, item.extra_tags);
            });
        }
    }).ajaxError(function(e, xhr, settings, exception) {
        addMessage("There was an error processing your request, please try again.", "error");
    });
});

function create_folder() {
    $.ajax({
        method: "POST",
        url: create_folder_url,
        data: $('#create-pseudofolder').serialize()
    }).done(function() {
        $('#pseudoContainer').foundation('reveal', 'close');
        loadTable();
        $("#create-pseudofolder").show();
        $("#progress").hide();
    }).always(function(data, textStatus, jqXHR) {

        var contentType = jqXHR.getResponseHeader("Content-Type");

        if (contentType == "application/javascript" || contentType == "application/json") {
            var json = $.parseJSON(jqXHR.responseText);

            $.each(json.django_messages, function (i, item) {
                addMessage(item.message, item.extra_tags);
            });
        }
    });
};<|endoftext|>


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

    angular
        .module('lecturer')
        .directive('engagementCanvas', engagementCanvas);

    function engagementCanvas() {
        var directive = {
            restrict: 'A',
            link: link,
            controller: EngagementCanvasController,
            controllerAs: 'engagementCanvas',
            bindToController: true
        };

        return directive;

        function link(scope, element, attrs, engagementCanvas) {
            console.log('Ready (Engagement Canvas link)');

            engagementCanvas.width = element.width();
            engagementCanvas.height = element.height();

            engagementCanvas.canvas = document.createElement('canvas');
            element.append(engagementCanvas.canvas);
            engagementCanvas.ctx = engagementCanvas.canvas.getContext('2d');

            engagementCanvas.canvas.width = engagementCanvas.width;
            engagementCanvas.canvas.height = engagementCanvas.height;

            engagementCanvas.heatmap = h337.create({
                container: element[0],
                radius: 50,
                blur: 1.0,
                minOpacity: 0.0,
                maxOpacity: 0.8,
                gradient: {
                    '0.20': 'lightblue',
                    '0.30': 'blue',
                    '0.40': 'green',
                    '0.55': 'yellow',
                    '0.70': 'orange',
                    '0.95': 'red'
                }
            });

            engagementCanvas.drawBackground(engagementCanvas.padding);
            engagementCanvas.pollEngagements(1000);
        }
    }

    /* @ngInject */
    function EngagementCanvasController(lecturesFactory) {
        console.log('Ready (Engagement Canvas Controller)');

        var engagementCanvas = this;
        engagementCanvas.pollId = undefined;
        engagementCanvas.padding = 30;
        engagementCanvas.canvas = {};
        engagementCanvas.ctx = {};

        engagementCanvas.drawBackground = drawBackground;
        engagementCanvas.drawDot = drawDot;
        engagementCanvas.pollEngagements = pollEngagements;

        function drawBackground(padding) {
            engagementCanvas.ctx.clearRect(
                0,
                0,
                engagementCanvas.canvas.width,
                engagementCanvas.canvas.height
            );

            engagementCanvas.ctx.beginPath();
            engagementCanvas.ctx.moveTo(padding,padding);
            engagementCanvas.ctx.lineTo(padding, engagementCanvas.canvas.height - padding);
            engagementCanvas.ctx.lineTo(
                engagementCanvas.canvas.width - padding,
                engagementCanvas.canvas.height - padding
            );
            engagementCanvas.ctx.lineWidth = 3;
            engagementCanvas.ctx.lineCap = 'round';
            engagementCanvas.ctx.stroke();

            engagementCanvas.ctx.fillStyle = 'black';
            engagementCanvas.ctx.textAlign = 'center';
            engagementCanvas.ctx.font = '18pt Calibri';
            engagementCanvas.ctx.fillText('Challenge', 200, 390);
            engagementCanvas.ctx.save();
            engagementCanvas.ctx.rotate(-Math.PI/2);
            engagementCanvas.ctx.fillText('Interest', -200, 20);
            engagementCanvas.ctx.restore();
        }

        function drawDot(x, y, padding) {
            if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
                var cartesianWidth = (engagementCanvas.canvas.width - 2*padding);
                var cartesianHeight = (engagementCanvas.canvas.height - 2*padding);
                var drawableX = (cartesianWidth*x + padding);
                var drawableY = (engagementCanvas.canvas.width - (cartesianHeight*y + padding));

                engagementCanvas.ctx.beginPath();
                engagementCanvas.ctx.fillStyle = 'rgba(0,0,0,0.5)';
                engagementCanvas.ctx.arc(drawableX, drawableY, 10, 0, 2*Math.PI);
                engagementCanvas.ctx.fill();
            }
        }

        function drawDots(engagements) {
            angular.forEach(engagements, function(engagement) {
                drawDot(
                    engagement.challenge,
                    engagement.interest,
                    engagementCanvas.padding
                );
            });
        }

        function updateHeatmap(engagements) {
            var padding = engagementCanvas.padding;
            var cartesianWidth = (engagementCanvas.width - 2*padding);
            var cartesianHeight = (engagementCanvas.height - 2*padding);

            var points = engagements.map(function(engagement) {
                var x = engagement.interest;
                var y = engagement.challenge;

                if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
                    var drawableX = (cartesianWidth*x + padding);
                    var drawableY = (engagementCanvas.height - (cartesianHeight*y + padding));

                    return {
                        x: drawableX,
                        y: drawableY,
                        value: 0.4
                    };
                }
            });
            engagementCanvas.heatmap.setData({
                min: 0,
                max: 1,
                data: points
            });
        }

        function pollEngagements(interval) {
            if (angular.isUndefined(engagementCanvas.pollId)) {
                engagementCanvas.pollId = setInterval(function() {

                    lecturesFactory
                        .getEngagements(function(engagements) {
                            drawBackground(engagementCanvas.padding);
                            updateHeatmap(engagements);
                        });

                }, interval);
            }
        }
    }
})();
<commit_msg>Fix interest and challenge axes being swapped in lecturer view<commit_after>(function() {
    'use strict';

    angular
        .module('lecturer')
        .directive('engagementCanvas', engagementCanvas);

    function engagementCanvas() {
        var directive = {
            restrict: 'A',
            link: link,
            controller: EngagementCanvasController,
            controllerAs: 'engagementCanvas',
            bindToController: true
        };

        return directive;

        function link(scope, element, attrs, engagementCanvas) {
            console.log('Ready (Engagement Canvas link)');

            engagementCanvas.width = element.width();
            engagementCanvas.height = element.height();

            engagementCanvas.canvas = document.createElement('canvas');
            element.append(engagementCanvas.canvas);
            engagementCanvas.ctx = engagementCanvas.canvas.getContext('2d');

            engagementCanvas.canvas.width = engagementCanvas.width;
            engagementCanvas.canvas.height = engagementCanvas.height;

            engagementCanvas.heatmap = h337.create({
                container: element[0],
                radius: 50,
                blur: 1.0,
                minOpacity: 0.0,
                maxOpacity: 0.8,
                gradient: {
                    '0.20': 'lightblue',
                    '0.30': 'blue',
                    '0.40': 'green',
                    '0.55': 'yellow',
                    '0.70': 'orange',
                    '0.95': 'red'
                }
            });

            engagementCanvas.drawBackground(engagementCanvas.padding);
            engagementCanvas.pollEngagements(1000);
        }
    }

    /* @ngInject */
    function EngagementCanvasController(lecturesFactory) {
        console.log('Ready (Engagement Canvas Controller)');

        var engagementCanvas = this;
        engagementCanvas.pollId = undefined;
        engagementCanvas.padding = 30;
        engagementCanvas.canvas = {};
        engagementCanvas.ctx = {};

        engagementCanvas.drawBackground = drawBackground;
        engagementCanvas.drawDot = drawDot;
        engagementCanvas.pollEngagements = pollEngagements;

        function drawBackground(padding) {
            engagementCanvas.ctx.clearRect(
                0,
                0,
                engagementCanvas.canvas.width,
                engagementCanvas.canvas.height
            );

            engagementCanvas.ctx.beginPath();
            engagementCanvas.ctx.moveTo(padding,padding);
            engagementCanvas.ctx.lineTo(padding, engagementCanvas.canvas.height - padding);
            engagementCanvas.ctx.lineTo(
                engagementCanvas.canvas.width - padding,
                engagementCanvas.canvas.height - padding
            );
            engagementCanvas.ctx.lineWidth = 3;
            engagementCanvas.ctx.lineCap = 'round';
            engagementCanvas.ctx.stroke();

            engagementCanvas.ctx.fillStyle = 'black';
            engagementCanvas.ctx.textAlign = 'center';
            engagementCanvas.ctx.font = '18pt Calibri';
            engagementCanvas.ctx.fillText('Challenge', 200, 390);
            engagementCanvas.ctx.save();
            engagementCanvas.ctx.rotate(-Math.PI/2);
            engagementCanvas.ctx.fillText('Interest', -200, 20);
            engagementCanvas.ctx.restore();
        }

        function drawDot(x, y, padding) {
            if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
                var cartesianWidth = (engagementCanvas.canvas.width - 2*padding);
                var cartesianHeight = (engagementCanvas.canvas.height - 2*padding);
                var drawableX = (cartesianWidth*x + padding);
                var drawableY = (engagementCanvas.canvas.width - (cartesianHeight*y + padding));

                engagementCanvas.ctx.beginPath();
                engagementCanvas.ctx.fillStyle = 'rgba(0,0,0,0.5)';
                engagementCanvas.ctx.arc(drawableX, drawableY, 10, 0, 2*Math.PI);
                engagementCanvas.ctx.fill();
            }
        }

        function drawDots(engagements) {
            angular.forEach(engagements, function(engagement) {
                drawDot(
                    engagement.challenge,
                    engagement.interest,
                    engagementCanvas.padding
                );
            });
        }

        function updateHeatmap(engagements) {
            var padding = engagementCanvas.padding;
            var cartesianWidth = (engagementCanvas.width - 2*padding);
            var cartesianHeight = (engagementCanvas.height - 2*padding);

            var points = engagements.map(function(engagement) {
                var x = engagement.challenge;
                var y = engagement.interest;

                if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
                    var drawableX = (cartesianWidth*x + padding);
                    var drawableY = (engagementCanvas.height - (cartesianHeight*y + padding));

                    return {
                        x: drawableX,
                        y: drawableY,
                        value: 0.4
                    };
                }
            });
            engagementCanvas.heatmap.setData({
                min: 0,
                max: 1,
                data: points
            });
        }

        function pollEngagements(interval) {
            if (angular.isUndefined(engagementCanvas.pollId)) {
                engagementCanvas.pollId = setInterval(function() {

                    lecturesFactory
                        .getEngagements(function(engagements) {
                            drawBackground(engagementCanvas.padding);
                            updateHeatmap(engagements);
                        });

                }, interval);
            }
        }
    }
})();
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Panel, Button, ProgressBar } from 'react-bootstrap';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { sendScoreRequest } from '../QuizActions';
import QuizPanelItem from './QuizPanelItem';
import styles from './style.css';

export class QuizPanel extends Component {

  constructor(props){
    super(props);
    this.state = { totalPercent: -1 };
  }

  componentDidMount() {
    this.setPoints();
  }

  countPoints = quiz => {
    if(this.correctAnswers(quiz) == 0){
      return quiz.options.filter(option => option.checked).length ? 0 : 1;
    }else{
      return Math.max(
        quiz.options.reduce((result, option) =>
            (option.checked ? ( option.answer ? +1 : -1 ) : 0) + result
        , 0), 0);
    }
  };

  //helper functions for quizzes
  correctAnswers = quiz => quiz.options.filter(option => option.answer).length;
  maxPoints = quiz => this.correctAnswers(quiz) || 1;
  correctUserAnswers = quiz => quiz.options.filter(option => option.answer == option.checked).length;

  quizFeedback = (wrongAnswers, selected) => {
    const correct = (wrongAnswers == 0);
    const textId = correct ? 'rightAnswerFeedback' : (selected === 0 ? 'selectOption' :
            (wrongAnswers === 1 ? 'oneWrongAnswer' : 'severalWrongAnswers'));
    const color = correct ? 'green' : ( selected ? 'red' : 'gray' );

    return (
               <FormattedMessage id={textId} values={{count: wrongAnswers}} />
            );
  };

  setPoints = () => {
    let maxPointsTotal = 0;
    let pointsTotal = 0;

    this.props.quizzes.forEach(quiz => {
      const maxPoints = this.maxPoints(quiz);

      maxPointsTotal += maxPoints;
      pointsTotal += quiz.points;

      if(maxPoints === quiz.points){
        quiz.options.forEach(option => {
          option.highlight = option.answer;
          option.disabled = true;
          option.checked = option.answer;
        });
        quiz.feedback = this.quizFeedback(0);
      }
    });
    let totalPercent = Math.round((pointsTotal / maxPointsTotal) * 100);
    if(isNaN(totalPercent)) totalPercent = 0;
    this.setState({ totalPercent });
  };

  verifyAnswers = () => {
    this.props.quizzes.forEach(quiz => {
      quiz.points = this.countPoints(quiz);
      const wrongCount = quiz.options.length - this.correctUserAnswers(quiz);
      const selectedCount = quiz.options.filter(option => option.checked).length;
      quiz.feedback = this.quizFeedback(wrongCount, selectedCount);
    });
    sendScoreRequest(this.props.quizzes);
    this.setPoints();
  };

  calculateQuizIndices = () => {
      this.props.quizzes.forEach((quiz, index) => quiz.index = index);
  };

  renderProgressBar = () => {
    return (

        <ProgressBar>
          <ProgressBar now={this.state.totalPercent} bsStyle="success" label={this.state.totalPercent + "%"} key={1}/>
        </ProgressBar>

    );

  };

  render(){
      this.calculateQuizIndices();
      const quizzes = this.props.quizzes;

      return (
        <Panel collapsible header={(

                   <FormattedMessage id={'quizPanelTitle'} />

                    {this.state.totalPercent + "%"}

)}>
            {quizzes.map((quiz,key) => <QuizPanelItem key={key} quiz={quiz} />)}
            {this.renderProgressBar()}
            <Button onClick={this.verifyAnswers}><FormattedMessage id={'check'} /></Button>
        </Panel>
    );
  }
}

QuizPanel.propTypes = {
    quizzes: PropTypes.array.isRequired,
};

export default injectIntl(QuizPanel);
<commit_msg>setPoints refaktoroitu<commit_after>import React, { Component, PropTypes } from 'react';
import { Panel, Button, ProgressBar } from 'react-bootstrap';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { sendScoreRequest } from '../QuizActions';
import QuizPanelItem from './QuizPanelItem';
import styles from './style.css';

export class QuizPanel extends Component {

  constructor(props){
    super(props);
    this.state = { totalPercent: -1 };
  }

  componentDidMount() {
    this.setPoints();
  }

  countPoints = quiz => {
    if(this.correctAnswers(quiz) == 0){
      return quiz.options.filter(option => option.checked).length ? 0 : 1;
    }else{
      return Math.max(
        quiz.options.reduce((result, option) =>
            (option.checked ? ( option.answer ? +1 : -1 ) : 0) + result
        , 0), 0);
    }
  };

  //helper functions for quizzes
  correctAnswers = quiz => quiz.options.filter(option => option.answer).length;
  maxPoints = quiz => this.correctAnswers(quiz) || 1;
  correctUserAnswers = quiz => quiz.options.filter(option => option.answer == option.checked).length;

  quizFeedback = (wrongAnswers, selected) => {
    const correct = (wrongAnswers == 0);
    const textId = correct ? 'rightAnswerFeedback' : (selected === 0 ? 'selectOption' :
            (wrongAnswers === 1 ? 'oneWrongAnswer' : 'severalWrongAnswers'));
    const color = correct ? 'green' : ( selected ? 'red' : 'gray' );

    return (
               <FormattedMessage id={textId} values={{count: wrongAnswers}} />
            );
  };

  setPoints = () => {
    const quizzes = this.props.quizzes;
    quizzes.forEach(quiz => {
      if(this.maxPoints(quiz) === quiz.points){
        quiz.options.forEach(option => {
          option.highlight = option.answer;
          option.disabled = true;
          option.checked = option.answer;
        });
        quiz.feedback = this.quizFeedback(0);
      }
    });

    const maxPointsTotal = quizzes.map(this.maxPoints).reduce((a, b) => a + b, 0);
    const pointsTotal = quizzes.map(quiz => quiz.points).reduce((a, b) => a + b, 0);
    let totalPercent = Math.round((pointsTotal / maxPointsTotal) * 100);
    if(isNaN(totalPercent)) totalPercent = 0;
    this.setState({ totalPercent });
  };

  verifyAnswers = () => {
    this.props.quizzes.forEach(quiz => {
      quiz.points = this.countPoints(quiz);
      const wrongCount = quiz.options.length - this.correctUserAnswers(quiz);
      const selectedCount = quiz.options.filter(option => option.checked).length;
      quiz.feedback = this.quizFeedback(wrongCount, selectedCount);
    });
    sendScoreRequest(this.props.quizzes);
    this.setPoints();
  };

  calculateQuizIndices = () => {
      this.props.quizzes.forEach((quiz, index) => quiz.index = index);
  };

  renderProgressBar = () => {
    return (

        <ProgressBar>
          <ProgressBar now={this.state.totalPercent} bsStyle="success" label={this.state.totalPercent + "%"} key={1}/>
        </ProgressBar>

    );

  };

  render(){
      this.calculateQuizIndices();
      const quizzes = this.props.quizzes;

      return (
        <Panel collapsible header={(

                   <FormattedMessage id={'quizPanelTitle'} />

                    {this.state.totalPercent + "%"}

)}>
            {quizzes.map((quiz,key) => <QuizPanelItem key={key} quiz={quiz} />)}
            {this.renderProgressBar()}
            <Button onClick={this.verifyAnswers}><FormattedMessage id={'check'} /></Button>
        </Panel>
    );
  }
}

QuizPanel.propTypes = {
    quizzes: PropTypes.array.isRequired,
};

export default injectIntl(QuizPanel);
<|endoftext|>


<commit_before>/*
Copyright 2006-2007, Open Source Applications Foundation

 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.
*/

/* The following are assertion functions available in all browsers
Currently the dynamic ones are not built into the IDE UI, but will
in the very near future.
*/

windmill.controller.asserts.assertRegistry = {
  'assertTrue': {
  expr: function (a) {
      if (typeof a != 'boolean') {
        throw('Bad argument to assertTrue.');
      }
      return a === true;
    },
  errMsg: 'expected true but was false.'
  },

  'assertFalse': {
  expr: function (a) {
      if (typeof a != 'boolean') {
        throw('Bad argument to assertFalse.');
      }
      return a === false;
    },
  errMsg: 'expected false but was true.'
  },

  'assertEquals': {
  expr: function (a, b) { return a === b; },
  errMsg: 'expected $1 but was $2.'
  },

  'assertNotEquals': {
  expr: function (a, b) { return a !== b; },
  errMsg: 'expected one of the two values not to be $1.'
  },

  'assertGreaterThan': {
  expr: function (a, b) { return a > b; },
  errMsg: 'expected a value greater than $2 but was $1.'
  },

  'assertLessThan': {
  expr: function (a, b) { return a < b; },
  errMsg: 'expected a value less than $2 but was $1.'
  },

  'assertNull': {
  expr: function (a) { return a === null; },
  errMsg: 'expected to be null but was $1.'
  },

  'assertNotNull': {
  expr: function (a) { return a !== null; },
  errMsg: 'expected not to be null but was null.'
  },

  'assertUndefined': {
  expr: function (a) { return typeof a == 'undefined'; },
  errMsg: 'expected to be undefined but was $1.'
  },

  'assertNotUndefined': {
  expr: function (a) { return typeof a != 'undefined'; },
  errMsg: 'expected not to be undefined but was undefined.'
  },

  'assertNaN': {
  expr: function (a) { return isNaN(a); },
  errMsg: 'expected $1 to be NaN, but was not NaN.'
  },

  'assertNotNaN': {
  expr: function (a) { return !isNaN(a); },
  errMsg: 'expected $1 not to be NaN, but was NaN.'
  },

  'assertEvaluatesToTrue': {
  expr: function (a) { return !!a; },
  errMsg: 'value of $1 does not evaluate to true.'
  },

  'assertEvaluatesToFalse': {
  expr: function (a) { return !a; },
  errMsg: 'value of $1 does not evaluate to false.'
  },

  'assertContains': {
  expr: function (a, b) {
      if (typeof a != 'string' || typeof b != 'string') {
        throw('Bad argument to assertContains.');
      }
      return (a.indexOf(b) > -1);
    },
  errMsg: 'value of $1 does not contain $2.'
  }
};

//Currently only does one level below the provided div
//To make it more thorough it needs recursion to be implemented later
windmill.controller.asserts.assertText = function (paramObject) {
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  var inner = n.innerHTML;
  if (n.textContent){
    inner = n.textContent;
  }
  else if (n.innerText) {
    inner = n.innerText;
  }
  // new lines and spaces break a lot of these, so removing them makes sense
  var iHTML = inner.replace(/^\s*|\s*$/g,'');

  if (iHTML == validator){
    return true;
  }

  // var found = n.textContent;
  // if (found == undefined)
  //   found = n.innerText;
  throw "Text '" + validator +
        "' was not found in the provided node.  Found instead: " + iHTML;
};

windmill.controller.asserts.assertTextIn = function (paramObject) {
  try { var n = lookupNode(paramObject, false); }
	catch(err){ n = false }

  var validator = paramObject.validator;

	//If no lookup was provided, search the whole document
	if (n == false || n == []){
		n = windmill.testWin().document.body;
	}
	var inner = n.innerHTML;
  if (n.textContent){
    inner = n.textContent;
  }
  else if (n.innerText){
    inner = n.innerText;
  }

  // new lines and spaces break a lot of these, so removing them makes sense
  var iHTML = inner.replace(/^\s*|\s*$/g,'');
  if (iHTML.indexOf(validator) != -1){
    return true;
  }
  else {
 	 // var found = n.textContent;
 	 // if (found == undefined)
  	//   found = n.innerText;
  	throw "Text '" + validator +
        "' was not found in the provided node.  Found instead: " + inner;
	}
};

//Assert that a specified node exists
windmill.controller.asserts.assertNode = function (paramObject) {
  var element = lookupNode(paramObject, false);
};

//Assert that a form element contains the expected value
windmill.controller.asserts.assertValue = function (paramObject) {
  //need to start moving test to use text instead of validator, its dumb
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if (n.value == undefined)
    throw "Element doesn't have a value";

  if (n.value != validator){
    throw "Found value \""+ n.value + "\" is not equal to \""+ validator+"\"";
  }
};

windmill.controller.asserts.assertValueIn = function (paramObject) {
  //need to start moving test to use text instead of validator, its dumb
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if (n.value == undefined)
    throw "Element doesn't have a value";

  if (n.value.indexOf(validator) == -1){
    throw "Found value \""+ n.value + "\" is not equal to \""+ validator+"\"";
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertJS = function (paramObject) {
  var js = paramObject.js;
  var result = windmill.testWin().eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertIDEJS = function (paramObject) {
  var js = paramObject.js;
  var result = eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Asserting javascript with an element object available
windmill.controller.asserts.assertElemJS = function (paramObject) {
  var element = lookupNode(paramObject, false);
  var js = paramObject.js;
  var result = eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertSelected = function (paramObject) {
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if ((n.options[n.selectedIndex].value != validator) && (n.options[n.selectedIndex].innerHTML != validator)){
    throw "Not selected, "+n.options[n.selectedIndex].value+" is not equal to " + validator;
  }
};

//Assert that a provided checkbox is checked
windmill.controller.asserts.assertChecked = function (paramObject) {
  var n = lookupNode(paramObject, false);

  if (!n.checked){
    throw "Checked property not true";
  }
};

// Assert that a an element's property is a particular value
windmill.controller.asserts.assertProperty = function (paramObject) {
  var element = lookupNode(paramObject, false);
  var vArray = paramObject.validator.split('|');
  if (vArray.length != 2)
    throw "Invalid validator '" + paramObject.validator + "'.  Use '|' to separate key from value.";

  var expected = "Expected property '" + vArray[0] + "' to have value '" + vArray[1] + "'. ";

  var value = eval ('element.' + vArray[0]+';');
  if (value == undefined)
    throw expected + "No '" + vArray[0] + "' property found.";

  if (value.indexOf(vArray[1]) != -1){
    return true;
  }
  if (String(value) == String(vArray[1])) {
    return true;
  }
  throw expected + "Found value '" + value + "' instead."
};

// Assert that a specified image has actually loaded
// The Safari workaround results in additional requests
// for broken images (in Safari only) but works reliably
windmill.controller.asserts.assertImageLoaded = function (paramObject) {
  var img = lookupNode(paramObject, false);
  if (!img || img.tagName != 'IMG') {
    throw "The node was not an image."
  }
  var comp = img.complete;
  var ret = null; // Return value

  // Workaround for Safari -- it only supports the
  // complete attrib on script-created images
  if (typeof comp == 'undefined') {
    test = new Image();
    // If the original image was successfully loaded,
    // src for new one should be pulled from cache
    test.src = img.src;
    comp = test.complete;
  }

  // Check the complete attrib. Note the strict
  // equality check -- we don't want undefined, null, etc.
  // --------------------------
  // False -- Img failed to load in IE/Safari, or is
  // still trying to load in FF
  if (comp === false) {
    throw "Image complete attrib false."
  }
  // True, but image has no size -- image failed to
  // load in FF
  else if (comp === true && img.naturalWidth == 0) {
    throw "Image has no size, failure to load."
  }
  // Otherwise all we can do is assume everything's
  // hunky-dory
  else {
    ret = true;
  }
  return ret;
};

windmill.controller.asserts._AssertFactory = new function () {
  var _this = this;
  function validateArgs(count, args) {
    if (!(args.length == count ||
	  (args.length == count + 1 && typeof(args[0]) == 'string') )) {
      throw('Incorrect arguments passed to assert function');
    }
  }
  function createErrMsg(msg, arr) {
    var str = msg;
    for (var i = 0; i < arr.length; i++) {
      //When calling jum functions arr is an array with a null entry
      if (arr[i] != null){
        var val = arr[i];
        var display = '<' + val.toString().replace(/\n/g, '') +
          '> (' + getTypeDetails(val) + ')';
        str = str.replace('$' + (i + 1).toString(), display);
      }
    }
    return str;
  }
  function getTypeDetails(val) {
    var r = typeof val;
    try {
      if (r == 'object' || r == 'function') {
        var m = val.constructor.toString().match(/function\s*([^( ]+)\(/);
						 if (m) { r = m[1]; }
						 else { r = 'Unknown Data Type' }
						 }
      }
      finally {
        r = r.substr(0, 1).toUpperCase() + r.substr(1);
        return r;
      }
    }
    this.createAssert = function (meth) {
      return function () {
      var args = Array.prototype.slice.call(arguments);
      args.unshift(meth);
      return _this.doAssert.apply(_this, args);
      }
    }
    this.doAssert = function () {
      // Convert arguments to real Array
      var args = Array.prototype.slice.call(arguments);
      // The actual assert method, e.g, 'equals'
      var meth = args.shift();
      // The assert object
      var asrt = windmill.controller.asserts.assertRegistry[meth];
      // The assert expresion
      var expr = asrt.expr;
      // Validate the args passed
      var valid = validateArgs(expr.length, args);
      // Pull off additional comment which may be first arg
      var comment = args.length > expr.length ?
        args.shift() : null;
      // Run the assert
      var res = expr.apply(window, args);
      if (res) {
	      return true;
      }
      else {
        var message = meth + ' -- ' +
        createErrMsg(asrt.errMsg, args);

	      throw new windmill.controller.asserts._WindmillAssertException(comment, message);
      }
    };
  };

// Create all the assert methods on windmill.controller.asserts
// Using the items in the assertRegistry
for (var meth in windmill.controller.asserts.assertRegistry) {
  windmill.controller.asserts[meth] = windmill.controller.asserts._AssertFactory.createAssert(meth);
  windmill.controller.asserts[meth].jsUnitAssert = true;
}

windmill.controller.asserts._WindmillAssertException = function (comment, message) {
  this.comment = comment;
  this.message = message;
};

<commit_msg>Bug in assertProperty, thanks sambao21<commit_after>/*
Copyright 2006-2007, Open Source Applications Foundation

 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.
*/

/* The following are assertion functions available in all browsers
Currently the dynamic ones are not built into the IDE UI, but will
in the very near future.
*/

windmill.controller.asserts.assertRegistry = {
  'assertTrue': {
  expr: function (a) {
      if (typeof a != 'boolean') {
        throw('Bad argument to assertTrue.');
      }
      return a === true;
    },
  errMsg: 'expected true but was false.'
  },

  'assertFalse': {
  expr: function (a) {
      if (typeof a != 'boolean') {
        throw('Bad argument to assertFalse.');
      }
      return a === false;
    },
  errMsg: 'expected false but was true.'
  },

  'assertEquals': {
  expr: function (a, b) { return a === b; },
  errMsg: 'expected $1 but was $2.'
  },

  'assertNotEquals': {
  expr: function (a, b) { return a !== b; },
  errMsg: 'expected one of the two values not to be $1.'
  },

  'assertGreaterThan': {
  expr: function (a, b) { return a > b; },
  errMsg: 'expected a value greater than $2 but was $1.'
  },

  'assertLessThan': {
  expr: function (a, b) { return a < b; },
  errMsg: 'expected a value less than $2 but was $1.'
  },

  'assertNull': {
  expr: function (a) { return a === null; },
  errMsg: 'expected to be null but was $1.'
  },

  'assertNotNull': {
  expr: function (a) { return a !== null; },
  errMsg: 'expected not to be null but was null.'
  },

  'assertUndefined': {
  expr: function (a) { return typeof a == 'undefined'; },
  errMsg: 'expected to be undefined but was $1.'
  },

  'assertNotUndefined': {
  expr: function (a) { return typeof a != 'undefined'; },
  errMsg: 'expected not to be undefined but was undefined.'
  },

  'assertNaN': {
  expr: function (a) { return isNaN(a); },
  errMsg: 'expected $1 to be NaN, but was not NaN.'
  },

  'assertNotNaN': {
  expr: function (a) { return !isNaN(a); },
  errMsg: 'expected $1 not to be NaN, but was NaN.'
  },

  'assertEvaluatesToTrue': {
  expr: function (a) { return !!a; },
  errMsg: 'value of $1 does not evaluate to true.'
  },

  'assertEvaluatesToFalse': {
  expr: function (a) { return !a; },
  errMsg: 'value of $1 does not evaluate to false.'
  },

  'assertContains': {
  expr: function (a, b) {
      if (typeof a != 'string' || typeof b != 'string') {
        throw('Bad argument to assertContains.');
      }
      return (a.indexOf(b) > -1);
    },
  errMsg: 'value of $1 does not contain $2.'
  }
};

//Currently only does one level below the provided div
//To make it more thorough it needs recursion to be implemented later
windmill.controller.asserts.assertText = function (paramObject) {
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  var inner = n.innerHTML;
  if (n.textContent){
    inner = n.textContent;
  }
  else if (n.innerText) {
    inner = n.innerText;
  }
  // new lines and spaces break a lot of these, so removing them makes sense
  var iHTML = inner.replace(/^\s*|\s*$/g,'');

  if (iHTML == validator){
    return true;
  }

  // var found = n.textContent;
  // if (found == undefined)
  //   found = n.innerText;
  throw "Text '" + validator +
        "' was not found in the provided node.  Found instead: " + iHTML;
};

windmill.controller.asserts.assertTextIn = function (paramObject) {
  try { var n = lookupNode(paramObject, false); }
	catch(err){ n = false }

  var validator = paramObject.validator;

	//If no lookup was provided, search the whole document
	if (n == false || n == []){
		n = windmill.testWin().document.body;
	}
	var inner = n.innerHTML;
  if (n.textContent){
    inner = n.textContent;
  }
  else if (n.innerText){
    inner = n.innerText;
  }

  // new lines and spaces break a lot of these, so removing them makes sense
  var iHTML = inner.replace(/^\s*|\s*$/g,'');
  if (iHTML.indexOf(validator) != -1){
    return true;
  }
  else {
 	 // var found = n.textContent;
 	 // if (found == undefined)
  	//   found = n.innerText;
  	throw "Text '" + validator +
        "' was not found in the provided node.  Found instead: " + inner;
	}
};

//Assert that a specified node exists
windmill.controller.asserts.assertNode = function (paramObject) {
  var element = lookupNode(paramObject, false);
};

//Assert that a form element contains the expected value
windmill.controller.asserts.assertValue = function (paramObject) {
  //need to start moving test to use text instead of validator, its dumb
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if (n.value == undefined)
    throw "Element doesn't have a value";

  if (n.value != validator){
    throw "Found value \""+ n.value + "\" is not equal to \""+ validator+"\"";
  }
};

windmill.controller.asserts.assertValueIn = function (paramObject) {
  //need to start moving test to use text instead of validator, its dumb
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if (n.value == undefined)
    throw "Element doesn't have a value";

  if (n.value.indexOf(validator) == -1){
    throw "Found value \""+ n.value + "\" is not equal to \""+ validator+"\"";
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertJS = function (paramObject) {
  var js = paramObject.js;
  var result = windmill.testWin().eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertIDEJS = function (paramObject) {
  var js = paramObject.js;
  var result = eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Asserting javascript with an element object available
windmill.controller.asserts.assertElemJS = function (paramObject) {
  var element = lookupNode(paramObject, false);
  var js = paramObject.js;
  var result = eval(js);
  if (result != true){
    throw "JavaScript did not return true."
  }
};

//Assert that a provided value is selected in a select element
windmill.controller.asserts.assertSelected = function (paramObject) {
  var n = lookupNode(paramObject, false);
  var validator = paramObject.validator;

  if ((n.options[n.selectedIndex].value != validator) && (n.options[n.selectedIndex].innerHTML != validator)){
    throw "Not selected, "+n.options[n.selectedIndex].value+" is not equal to " + validator;
  }
};

//Assert that a provided checkbox is checked
windmill.controller.asserts.assertChecked = function (paramObject) {
  var n = lookupNode(paramObject, false);

  if (!n.checked){
    throw "Checked property not true";
  }
};

// Assert that a an element's property is a particular value
windmill.controller.asserts.assertProperty = function (paramObject) {
  var element = lookupNode(paramObject, false);
  var arr = paramObject.validator.split('|');

  //if we didnt get two params
  if (arr.length != 2) {
    throw "Invalid validator '" + paramObject.validator + "'.  Use '|' to separate key from value.";
  }

  //base exception
  var expected = "Expected property '" + arr[0] + "' to have value '" + arr[1] + "'. ";
  var value = String(eval('element.' + arr[0]+';'));

  //cases where we achieve success
  if (value == undefined){
    throw expected + "No '" + arr[0] + "' property found.";
  }
  else if (value.indexOf(arr[1]) != -1){
    return true;
  }
  else if (String(value) == String(arr[1])) {
    return true;
  }

  //fail throw exception
  throw expected + "Found value '" + value + "' instead."
};

// Assert that a specified image has actually loaded
// The Safari workaround results in additional requests
// for broken images (in Safari only) but works reliably
windmill.controller.asserts.assertImageLoaded = function (paramObject) {
  var img = lookupNode(paramObject, false);
  if (!img || img.tagName != 'IMG') {
    throw "The node was not an image."
  }
  var comp = img.complete;
  var ret = null; // Return value

  // Workaround for Safari -- it only supports the
  // complete attrib on script-created images
  if (typeof comp == 'undefined') {
    test = new Image();
    // If the original image was successfully loaded,
    // src for new one should be pulled from cache
    test.src = img.src;
    comp = test.complete;
  }

  // Check the complete attrib. Note the strict
  // equality check -- we don't want undefined, null, etc.
  // --------------------------
  // False -- Img failed to load in IE/Safari, or is
  // still trying to load in FF
  if (comp === false) {
    throw "Image complete attrib false."
  }
  // True, but image has no size -- image failed to
  // load in FF
  else if (comp === true && img.naturalWidth == 0) {
    throw "Image has no size, failure to load."
  }
  // Otherwise all we can do is assume everything's
  // hunky-dory
  else {
    ret = true;
  }
  return ret;
};

windmill.controller.asserts._AssertFactory = new function () {
  var _this = this;
  function validateArgs(count, args) {
    if (!(args.length == count ||
	  (args.length == count + 1 && typeof(args[0]) == 'string') )) {
      throw('Incorrect arguments passed to assert function');
    }
  }
  function createErrMsg(msg, arr) {
    var str = msg;
    for (var i = 0; i < arr.length; i++) {
      //When calling jum functions arr is an array with a null entry
      if (arr[i] != null){
        var val = arr[i];
        var display = '<' + val.toString().replace(/\n/g, '') +
          '> (' + getTypeDetails(val) + ')';
        str = str.replace('$' + (i + 1).toString(), display);
      }
    }
    return str;
  }
  function getTypeDetails(val) {
    var r = typeof val;
    try {
      if (r == 'object' || r == 'function') {
        var m = val.constructor.toString().match(/function\s*([^( ]+)\(/);
						 if (m) { r = m[1]; }
						 else { r = 'Unknown Data Type' }
						 }
      }
      finally {
        r = r.substr(0, 1).toUpperCase() + r.substr(1);
        return r;
      }
    }
    this.createAssert = function (meth) {
      return function () {
      var args = Array.prototype.slice.call(arguments);
      args.unshift(meth);
      return _this.doAssert.apply(_this, args);
      }
    }
    this.doAssert = function () {
      // Convert arguments to real Array
      var args = Array.prototype.slice.call(arguments);
      // The actual assert method, e.g, 'equals'
      var meth = args.shift();
      // The assert object
      var asrt = windmill.controller.asserts.assertRegistry[meth];
      // The assert expresion
      var expr = asrt.expr;
      // Validate the args passed
      var valid = validateArgs(expr.length, args);
      // Pull off additional comment which may be first arg
      var comment = args.length > expr.length ?
        args.shift() : null;
      // Run the assert
      var res = expr.apply(window, args);
      if (res) {
	      return true;
      }
      else {
        var message = meth + ' -- ' +
        createErrMsg(asrt.errMsg, args);

	      throw new windmill.controller.asserts._WindmillAssertException(comment, message);
      }
    };
  };

// Create all the assert methods on windmill.controller.asserts
// Using the items in the assertRegistry
for (var meth in windmill.controller.asserts.assertRegistry) {
  windmill.controller.asserts[meth] = windmill.controller.asserts._AssertFactory.createAssert(meth);
  windmill.controller.asserts[meth].jsUnitAssert = true;
}

windmill.controller.asserts._WindmillAssertException = function (comment, message) {
  this.comment = comment;
  this.message = message;
};

<|endoftext|>


<commit_before>/* eslint spaced-comment: 0 */
const assert = require('chai').assert;

/// title: Bookshop in Rome
/// type: arcade-mode

/// catgories:
/// algorithms
/// sorting

/// images:
/// public/img/challenges/pexels-photo-358717.jpeg

/// description:
/// On your last day of vacation, a quaint used bookstore catches your eye on one of the smaller streets of Rome. "Perhaps this bookstore may have that out of print book I have been looking for all these years.". As you walk inside, you note the large pile of books in the back of the store and the sparsely-furnished bookshelves throughout. The shopkeep, a thin elderly man with combed back white hair and spectacles, seems to be deep in the process of organizing one of the bookshelves. You browse each aisle with ease due of the sparseness, but also because of your familiarity with the cover design of the book. It is then that you finally notice it on the bookshelf with other visibly old books. "They have it!" you think estatically. Of course, you made sure multiple times.
/// As you approach the shopkeep to purchase the book, he becomes visibly startled at your presence. "Goodness! I thought I had locked the door. I apologize, but due to the recent earthquake most of the books need to be resorted before I can reopen the store."
/// Noting the book you have in your hand, he continues. "That's quite the rare book. I can offer it to you if you help me sort through all the books here. I cannot sell it for anything else at this point."
/// Understanding that your flight is tomorrow, you only have today to sort through all the books. Luckily for you, you know a few sorting algorithms. You accept the shopkeep's offer.
/// Given an array of book author last names, sort the books without using Array.prototype.sort().

/// challengeSeed:
function sortBooks (arr) {
  // Good luck!
  return true;
}

/// solutions:
function sortBooks (arr) {
  if (arr.length <= 1) {
    return arr;
  }
  // quick sort implementation
  const pivot = arr[Math.floor(arr.length / 2)]; // use approx middle element as pivot
  let leftIndex = 0;
  let rightIndex = arr.length - 1;
  while (leftIndex < rightIndex) {
    if (arr[leftIndex] >= pivot) {
      if (arr[rightIndex] <= pivot) {
        [arr[leftIndex], arr[rightIndex]] = [arr[rightIndex], arr[leftIndex]]; // swap
      }
      rightIndex--;
    }
    else leftIndex++;
  }

  const rightSide = arr.splice(leftIndex);
  const leftSide = arr;

  return sortBooks(leftSide).concat(sortBooks(rightSide));
}

/// tail:
function isSorted (arr) {
  const check = i => (i === arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);
  return check(0);
}

/// tests:
assert(typeof sortBooks === 'function', 'message: sortBooks is a function.');
assert(isSorted(sortBooks(['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano'])), 'message: sortBooks returns a sorted array.');
assert.sameMembers(sortBooks(['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano']), ['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano']);
assert.strictEqual(code.search(/\.sort\(/), -1, 'message: sortBooks should not use the built-in .sort() method.');
<commit_msg>add image to desc and add missing "message"<commit_after>/* eslint spaced-comment: 0 */
const assert = require('chai').assert;

/// title: Bookshop in Rome
/// type: arcade-mode

/// catgories:
/// algorithms
/// sorting

/// images:
/// public/img/challenges/pexels-photo-358717.jpeg

/// description:
///
/// On your last day of vacation, a quaint used bookstore catches your eye on one of the smaller streets of Rome. "Perhaps this bookstore may have that out of print book I have been looking for all these years.". As you walk inside, you note the large pile of books in the back of the store and the sparsely-furnished bookshelves throughout. The shopkeep, a thin elderly man with combed back white hair and spectacles, seems to be deep in the process of organizing one of the bookshelves. You browse each aisle with ease due of the sparseness, but also because of your familiarity with the cover design of the book. It is then that you finally notice it on the bookshelf with other visibly old books. "They have it!" you think estatically. Of course, you made sure multiple times.
/// As you approach the shopkeep to purchase the book, he becomes visibly startled at your presence. "Goodness! I thought I had locked the door. I apologize, but due to the recent earthquake most of the books need to be resorted before I can reopen the store."
/// Noting the book you have in your hand, he continues. "That's quite the rare book. I can offer it to you if you help me sort through all the books here. I cannot sell it for anything else at this point."
/// Understanding that your flight is tomorrow, you only have today to sort through all the books. Luckily for you, you know a few sorting algorithms. You accept the shopkeep's offer.
/// Given an array of book author last names, sort the books without using Array.prototype.sort().

/// challengeSeed:
function sortBooks (arr) {
  // Good luck!
  return true;
}

/// solutions:
function sortBooks (arr) {
  if (arr.length <= 1) {
    return arr;
  }
  // quick sort implementation
  const pivot = arr[Math.floor(arr.length / 2)]; // use approx middle element as pivot
  let leftIndex = 0;
  let rightIndex = arr.length - 1;
  while (leftIndex < rightIndex) {
    if (arr[leftIndex] >= pivot) {
      if (arr[rightIndex] <= pivot) {
        [arr[leftIndex], arr[rightIndex]] = [arr[rightIndex], arr[leftIndex]]; // swap
      }
      rightIndex--;
    }
    else leftIndex++;
  }

  const rightSide = arr.splice(leftIndex);
  const leftSide = arr;

  return sortBooks(leftSide).concat(sortBooks(rightSide));
}

/// tail:
function isSorted (arr) {
  const check = i => (i === arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);
  return check(0);
}

/// tests:
assert(typeof sortBooks === 'function', 'message: sortBooks is a function.');
assert(isSorted(sortBooks(['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano'])), 'message: sortBooks returns a sorted array.');
assert.sameMembers(sortBooks(['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano']), ['Rossi', 'Russo', 'Ferarri', 'Esposito', 'Bianchi', 'Romano'], 'message: sortBooks returns an array that is unchanged except for order.');
assert.strictEqual(code.search(/\.sort\(/), -1, 'message: sortBooks should not use the built-in .sort() method.');
<|endoftext|>