import Churn from "./churn" ; import Complexity from "./complexity" ; import { Options , Path , Sort } from "./types" ; import { buildDebugger } from "../utils" ; const DEFAULT_CHURN = 1 ; const DEFAULT_COMPLEXITY = 1 ; const internal = { debug : buildDebugger ( "statistics" ) } ; export default class Statistics { public readonly path : Path ; public readonly churn : number ; public readonly complexity : number ; public readonly score : number ; constructor ( path , churn , complexity ) { this . path = path ; this . churn = churn ; this . complexity = complexity ; this . score = this . churn * this . complexity ; } public static async compute ( options ) { internal . debug ( `invoked with options: ${ JSON . stringify ( options ) }` ) ; internal . debug ( `using cwd: ${ process . cwd ( ) }` ) ; const churns = await Churn . compute ( options ) ; const paths = Array . from ( churns . keys ( ) ) ; const complexities = await Complexity . compute ( paths , options ) ; const statistics = paths . map ( toStatistics ( churns , complexities ) ) . sort ( sort ( options . sort ) ) . filter ( limit ( options . limit ) ) ; return toMap ( statistics ) ; } } function toStatistics ( churns , complexities ) { return ( path ) : Statistics => { const churn = churns . get ( path ) || DEFAULT_CHURN ; const complexity = complexities . get ( path ) || DEFAULT_COMPLEXITY ; return new Statistics ( path , churn , complexity ) ; } ; } function limit ( limit ) { return ( statistics , i ) : boolean => ! limit || i < limit ; } function sort ( sort ) { return ( statisticsA , statisticsB ) : number => { if ( sort === "score" || sort === "ratio" ) { return statisticsB . score - statisticsA . score ; } if ( sort === "churn" ) { return statisticsB . churn - statisticsA . churn ; } if ( sort === "complexity" ) { return statisticsB . complexity - statisticsA . complexity ; } if ( sort === "file" ) { const fileAPath = statisticsA . path ; const fileBPath = statisticsB . path ; return fileAPath . localeCompare ( fileBPath ) ; } return 0 ; } ; } function toMap ( statistics ) { return statistics . reduce ( ( map , statistics ) => { map . set ( statistics . path , statistics ) ; return map ; } , new Map ( ) ) ; }