Skip to content

Commit

Permalink
#69 Create percent-complete function.
Browse files Browse the repository at this point in the history
  • Loading branch information
rlmcneary2 committed Jun 19, 2024
1 parent 72e3b3a commit d00f4c0
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 1 deletion.
65 changes: 65 additions & 0 deletions public/percent-complete/percent-complete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { JiraIssue } from "../shared/issue-data/issue-data.js";

/**
* @param { JiraIssue[] } issues
* @param { PercentCompleteOptions } options
*/
export function percentComplete(issues, options) {
console.log(`percentComplete: issues=`, issues);

const map = buildMap(issues, options);

console.log("percentComplete: map=", map);
}

/**
* @param {JiraIssue[]} issues
* @param {PercentCompleteOptions} options
* @returns {Record<string, CompletionIssue>>}
*/
function buildMap(issues, options) {
return issues.reduce((acc, issue) => {
const key = options.getIssueKey(issue);
const parentKey = options.getParentKey(issue);

acc[key] = {
children: acc[key]?.children ?? [],
hierarchyLevel: issue.fields["Issue Type"].hierarchyLevel,
parentKey,
type: options.getType(issue),
};

if (parentKey) {
if (acc[parentKey]) {
acc[parentKey].children.push(key);
} else {
acc[parentKey] = { children: [key] };
}
}

return acc;
}, {});
}

/**
* @typedef CompletionIssue
* @property {CompletionIssue[]} children
* @property {number} hierarchyLevel
* @property {string} type
*/

/**
* @typedef PercentCompleteOptions
* @property {(issue: JiraIssue) => number} getConfidence
* @property {(teamKey: string) => number} getDaysPerSprint
* @property {(issue: JiraIssue) => string} getDueDate
* @property {(issue: JiraIssue) => number} getEstimate
* @property {(issue: JiraIssue) => string} getIssueKey
* @property {(issue: JiraIssue) => string | undefined} getParentKey
* @property {(issue: JiraIssue) => string} getStartDate
* @property {(issue: JiraIssue) => string} getTeamKey
* @property {(issue: JiraIssue) => string} getType
* @property {(teamKey: string) => number} getVelocity
* @property {string[]} includeTypes
* @property {number} uncertaintyWeight
*/
102 changes: 102 additions & 0 deletions public/shared/issue-data/issue-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* @param {JiraIssue} issue
* @returns {number}
*/
export function getConfidence({ fields }) {
return fields.Confidence;
}

/**
* @param {string} teamKey
* @returns {number}
*/
export function getDaysPerSprint(teamKey) {
return 10;
}

/**
* @param {JiraIssue} issue
* @returns {string | null}
*/
export function getDueDate({ fields }) {
return fields["Due date"];
}

/**
* @param {JiraIssue} issue
* @returns {number}
*/
export function getEstimate({ fields }) {
return fields["Story points median"];
}

/**
* @param {JiraIssue} issue
* @returns {string}
*/
export function getIssueKey({ key }) {
return key;
}

/**
* @param {JiraIssue} issue
* @returns {string | void}
*/
export function getParentKey({ fields }) {
return fields["Parent Link"].data?.key;
}

/**
* @param {JiraIssue} issue
* @returns {string | null}
*/
export function getStartDate({ fields }) {
return fields["Start date"];
}

/**
* @param {JiraIssue} issue
* @returns {string}
*/
export function getTeamKeyDefault({ fields }) {
var matches = fields.Summary.match(/M\d: ([^:]+): /);
if (matches) {
return fields["Project key"] + ":" + matches[1];
} else {
return fields["Project key"];
}
}

/**
* @param {JiraIssue} issue
* @returns {string}
*/
export function getType({ fields }) {
return fields["Issue Type"].name;
}

/**
* @param {string} teamKey
* @returns {number}
*/
export function getVelocity(teamKey) {
return 21;
}

/**
* @typedef {{
* fields: {
* Confidence: number,
* 'Due date': string | null,
* 'Issue Type': { hierarchyLevel: number, name: string },
* 'Parent Link': { data: { key: string } },
* 'Project Key': string,
* 'Start date': string | null,
* Status: { name: string }
* 'Story points median'?: number,
* Summary: string
* },
* id: string,
* key: string
* }} JiraIssue
*/
32 changes: 31 additions & 1 deletion public/timeline-report.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { StacheElement, type, ObservableObject, ObservableArray } from "./can.js";
import { calculationKeysToNames } from "./prepare-issues/date-data.js";
import { percentComplete } from "./percent-complete/percent-complete.js"
import {
getConfidence,
getDaysPerSprint,
getDueDate,
getEstimate,
getIssueKey,
getParentKey,
getStartDate,
getTeamKeyDefault,
getType,
getVelocity
} from "./shared/issue-data/issue-data.js"




Expand Down Expand Up @@ -253,6 +267,8 @@ const configurationView = `
</div>`;

const UNCERTAINTY_WEIGHT_DEFAULT = 80;


export class TimelineReport extends StacheElement {
static view = `
Expand Down Expand Up @@ -779,7 +795,21 @@ export class TimelineReport extends StacheElement {
issuesPromise, serverInfoPromise
]).then(([issues, serverInfo]) => {
const formatted = rawIssuesToBaseIssueFormat(issues, serverInfo);
console.log(formatted);
percentComplete(issues, {
getType,
getTeamKey: getTeamKeyDefault,
getDaysPerSprint,
getIssueKey,
getParentKey,
getVelocity,
getEstimate,
getConfidence,
getStartDate,
getDueDate,
//getParallelWorkLimit: (TEAM_KEY) => 1
includeTypes: ["Epic"],
uncertaintyWeight: UNCERTAINTY_WEIGHT_DEFAULT,
});
return formatted;
})
}
Expand Down

0 comments on commit d00f4c0

Please sign in to comment.