(function () { 'use strict'; var mod = angular.module('reportingModule', []); var serviceId = 'reportingService'; mod.factory(serviceId, ['usefulService', reportingService]); function reportingService(usefulService) { var service = { setupCompetencyIds: setupCompetencyIds, userSummaryCompetencySummer: userSummaryCompetencySummer, calculateItemsForCompetencies: calculateItemsForCompetencies, summaryCompetencySummer: summaryCompetencySummer }; return service; function calculateItemsForCompetencies(competency, summarys) { //create an object that we can populate and then copy for each user and for a summary of all users //properties are arrays used to populate the charts - the order of the item in the array is vital - e.g the 2nd itemTotal (chart data value) goes with the competencyName (chart label for that data point) var summaryBlank = { itemTotals: [], //total number of items for each competency competencyNames: [], //names of each top sub level competency topLevelCompetencyIds: [], //the ids of each top sub level competency groupedCompetencyIds: [], //an array of arrays - each array is the collection of child competency ids for the parent numTopLevelCompetencies: competency.branches.length //how many top level competencies are there }; //for each child competency fill in the blank for (var j = 0; j < summaryBlank.numTopLevelCompetencies; j++) { var competencyIdsForTopLevel = []; setupCompetencyIds([competency.branches[j]], competencyIdsForTopLevel); summaryBlank.competencyNames.push(competency.branches[j].name); summaryBlank.topLevelCompetencyIds.push(competency.branches[j].id); summaryBlank.groupedCompetencyIds.push(competencyIdsForTopLevel); summaryBlank.itemTotals.push(0); } //allocate a copy of the blank for the summary (all users) var dataSummary = angular.copy(summaryBlank); dataSummary.allCompetencyIds = []; //the summary needs a list of all possible competency ids for (var i = 0; i < dataSummary.numTopLevelCompetencies; i++) { dataSummary.allCompetencyIds = dataSummary.allCompetencyIds.concat(dataSummary.groupedCompetencyIds[i]); } //for each user summary for (var i = 0; i < summarys.length; i++) { var currentSummary = summarys[i]; //allocate a summary blank for the user summary currentSummary.dataSummary = angular.copy(summaryBlank); var items = currentSummary.items; if (!items) items = currentSummary; //for each item in the user summary increment the competency counts for (var j = 0; j < items.length; j++) { //for each competency associated with the item for (var k = 0; k < items[j].competencies.length; k++) { incrementTopLevelCompetency(currentSummary.dataSummary, dataSummary, items[j].competencies[k]); } } } return dataSummary; } function incrementTopLevelCompetency(userSummary, summary, competencyId) { //for every top level competency we have an array of child competency ids - we are working out which top level competency the competencyid belongs to and then incrementing the total at the same array location //go through each top level competency for (var i = 0; i < userSummary.numTopLevelCompetencies; i++) { //does the competency id exist in the group of ids for that top level competency //if it does increment the total for the user summary and for the overall summary at the same array location if (userSummary.groupedCompetencyIds[i].indexOf(competencyId) > -1) { userSummary.itemTotals[i]++; summary.itemTotals[i]++; break; //we can break because once we have found it we know that child competency won't exist as a child of another parent - there ain't no adoption in the frameworks world } } } //get a flat array of competency ids from the competency tree structure - we need this to pass to MS API to get the item summary we need for reporting function setupCompetencyIds(competencies, comps) { if (!competencies) return null; //go through each competency and add it to the list, recursively add the children too for (var i = 0; i < competencies.length; i++) { if (competencies[i] && competencies[i].id) { comps.push(competencies[i].id); //if there are any child competencies then call this function recursively for the children if (competencies[i].branches && competencies[i].branches.length > 0) setupCompetencyIds(competencies[i].branches, comps); } } return comps; } //calculate the item type summarys for each user and for the group as a whole function userSummaryCompetencySummer(competencyIds, userSummarys) { //for the group as a whole create an array to hold totals for each item type var itemSummary = [ { name: 'status', numItems: 0 }, { name: 'file', numItems: 0 }, { name: 'embed', numItems: 0 }, { name: 'weblink', numItems: 0 }, { name: 'form', numItems: 0 }, { name: 'video', numItems: 0 }, { name: 'badge', numItems: 0 }, { name: 'image', numItems: 0 }, { name: 'myprogress assessment', numItems: 0 } ]; //because its javascript we can also add a property to the array to hold the totals of all items (so we can work out percentages) itemSummary.totalNumItems = 0; //go through each user summary for (var i = 0; i < userSummarys.length; i++) { //do something similar for each user summary var userSummary = userSummarys[i]; userSummary.totalNumItems = 0; //holds total number of items for this user userSummary.itemSummary = [ { name: 'status', numItems: 0 }, { name: 'file', numItems: 0 }, { name: 'embed', numItems: 0 }, { name: 'weblink', numItems: 0 }, { name: 'form', numItems: 0 }, { name: 'video', numItems: 0 }, { name: 'badge', numItems: 0 }, { name: 'image', numItems: 0 }, { name: 'myprogress assessment', numItems: 0 } ]; var userItems = userSummary.items; if (!userItems) userItems = userSummary; //go through each item in the user summary for (var j = 0; j < userItems.length; j++) { var item = userItems[j]; //because we are only reporting on items that match a subset of competencies we only consider items with those competencies if (item.competencies && item.competencies.length > 0) { //go through each of the competencies chosen by the report viewer for (var k = 0; k < competencyIds.length; k++) { //now go through each competency in the item - if it matches we know that the item needs to be added to one of our totals - but which one????? for (var l = 0; l < item.competencies.length; l++) { if (item.competencies[l] === competencyIds[k]) { //increment the total number of items for the user summary and for the overall summary userSummary.totalNumItems++; itemSummary.totalNumItems++; //now work out which item type it was an increment the total at the same location in the array if (item.itemType.toLowerCase() === 'status') { userSummary.itemSummary[0].numItems++; itemSummary[0].numItems++; } else if (item.itemType.toLowerCase() === 'file') { userSummary.itemSummary[1].numItems++; itemSummary[1].numItems++; } else if (item.itemType.toLowerCase() === 'embed') { userSummary.itemSummary[2].numItems++; itemSummary[2].numItems++; } else if (item.itemType.toLowerCase() === 'weblink') { userSummary.itemSummary[3].numItems++; itemSummary[3].numItems++; } else if (item.itemType.toLowerCase() === 'form') { userSummary.itemSummary[4].numItems++; itemSummary[4].numItems++; } else if (item.itemType.toLowerCase() === 'video') { userSummary.itemSummary[5].numItems++; itemSummary[5].numItems++; } else if (item.itemType.toLowerCase() === 'badge') { userSummary.itemSummary[6].numItems++; itemSummary[6].numItems++; } else if (item.itemType.toLowerCase() === 'image') { userSummary.itemSummary[7].numItems++; itemSummary[7].numItems++; } else if (item.itemType.toLowerCase() === 'myprogress assessment') { userSummary.itemSummary[8].numItems++; itemSummary[8].numItems++; } } } } } } //at this point we can calculate (for the user) what percentage of the total items are each item type, we can also sort by the highest number of items calculateAndSortItemSummary(userSummary.itemSummary, userSummary.totalNumItems); } //at this point we can calculate (for the overll summary) what percentage of the total items are each item type, we can also sort by the highest number of items calculateAndSortItemSummary(itemSummary, itemSummary.totalNumItems); return itemSummary; } function summaryCompetencySummer(competencyIds, userSummarys) { //for the group as a whole create an array to hold totals for each item type var itemSummary = [ { name: 'status', numItems: 0 }, { name: 'file', numItems: 0 }, { name: 'embed', numItems: 0 }, { name: 'weblink', numItems: 0 }, { name: 'form', numItems: 0 }, { name: 'video', numItems: 0 }, { name: 'badge', numItems: 0 }, { name: 'myprogress assessment', numItems: 0 } ]; //because its javascript we can also add a property to the array to hold the totals of all items (so we can work out percentages) itemSummary.totalNumItems = 0; //go through each user summary for (var i = 0; i < userSummarys.length; i++) { //do something similar for each user summary var userSummary = userSummarys[i]; userSummary.totalNumItems = 0; //holds total number of items for this user //go through each item in the user summary for (var j = 0; j < userSummary.items.length; j++) { var item = userSummary.items[j]; //because we are only reporting on items that match a subset of competencies we only consider items with those competencies if (item.competencies && item.competencies.length > 0) { //go through each of the competencies chosen by the report viewer for (var k = 0; k < competencyIds.length; k++) { //now go through each competency in the item - if it matches we know that the item needs to be added to one of our totals - but which one????? for (var l = 0; l < item.competencies.length; l++) { if (item.competencies[l] === competencyIds[k]) { itemSummary.totalNumItems++; //now work out which item type it was an increment the total at the same location in the array if (item.itemType === 'status') userSummary.itemSummary[0].numItems++; else if (item.itemType === 'file') userSummary.itemSummary[1].numItems++; else if (item.itemType === 'embed') userSummary.itemSummary[2].numItems++; else if (item.itemType === 'weblink') userSummary.itemSummary[3].numItems++; else if (item.itemType === 'form') userSummary.itemSummary[4].numItems++; else if (item.itemType === 'video') userSummary.itemSummary[5].numItems++; else if (item.itemType === 'badge') userSummary.itemSummary[6].numItems++; else if (item.itemType === 'image') userSummary.itemSummary[7].numItems++; else if (item.itemType.toLowerCase() === 'myprogress assessment') { userSummary.itemSummary[8].numItems++; } } } } } } } //at this point we can calculate (for the overll summary) what percentage of the total items are each item type, we can also sort by the highest number of items calculateAndSortItemSummary(itemSummary, itemSummary.totalNumItems); return itemSummary; } //for an item summary work out percentages for each item type compared to the total number of items function calculateAndSortItemSummary(itemSummary, totalNumItems) { for (var x = 0; x < itemSummary.length; x++) { itemSummary[x].percentageOfTotal = (itemSummary[x].numItems / totalNumItems) * 100; } //sort the item summary by the numitems property - highest first itemSummary.sort(usefulService.dynamicSort('-numItems')); } //for a competency get a flat array of all the child competency ids - uses recursion to go through each child level function getCompetencyIds(competency, ids) { if (!competency) return; if (!ids) ids = []; ids.push(competency.id); if (competency.childCompetencies && competency.childCompetencies.length > 0) { for (var i = 0; i < competency.childCompetencies.length; i++) { getCompetencyIds(competency.childCompetencies[i], ids); } } } } })();