11// Copyright (c) jdneo. All rights reserved.
22// Licensed under the MIT license.
33
4- import * as _ from "lodash" ;
54import * as os from "os" ;
65import * as path from "path" ;
76import * as vscode from "vscode" ;
8- import * as list from "../commands/list" ;
9- import { leetCodeChannel } from "../leetCodeChannel" ;
107import { leetCodeManager } from "../leetCodeManager" ;
11- import { Category , defaultProblem , IProblem , ProblemState } from "../shared" ;
12- import { getWorkspaceConfiguration } from "../utils/workspaceUtils " ;
8+ import { Category , defaultProblem , ProblemState } from "../shared" ;
9+ import { explorerNodeManager } from "./explorerNodeManager " ;
1310import { LeetCodeNode } from "./LeetCodeNode" ;
1411
1512export class LeetCodeTreeDataProvider implements vscode . TreeDataProvider < LeetCodeNode > {
1613
17- private treeData : {
18- Difficulty : Map < string , IProblem [ ] > ,
19- Tag : Map < string , IProblem [ ] > ,
20- Company : Map < string , IProblem [ ] > ,
21- Favorite : IProblem [ ] ,
22- } ;
23-
2414 private onDidChangeTreeDataEvent : vscode . EventEmitter < any > = new vscode . EventEmitter < any > ( ) ;
2515 // tslint:disable-next-line:member-ordering
2616 public readonly onDidChangeTreeData : vscode . Event < any > = this . onDidChangeTreeDataEvent . event ;
2717
2818 constructor ( private context : vscode . ExtensionContext ) { }
2919
3020 public async refresh ( ) : Promise < void > {
31- await this . getProblemData ( ) ;
21+ await explorerNodeManager . refreshCache ( ) ;
3222 this . onDidChangeTreeDataEvent . fire ( ) ;
3323 }
3424
@@ -49,7 +39,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
4939 return {
5040 label : element . isProblem ? `[${ element . id } ] ${ element . name } ` : element . name ,
5141 tooltip : this . getSubCategoryTooltip ( element ) ,
52- id : `${ idPrefix } .${ element . parentName } . ${ element . id } ` ,
42+ id : `${ idPrefix } .${ element . id } ` ,
5343 collapsibleState : element . isProblem ? vscode . TreeItemCollapsibleState . None : vscode . TreeItemCollapsibleState . Collapsed ,
5444 contextValue : element . isProblem ? "problem" : element . id . toLowerCase ( ) ,
5545 iconPath : this . parseIconPathFromProblemState ( element ) ,
@@ -63,91 +53,28 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
6353 new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
6454 id : "notSignIn" ,
6555 name : "Sign in to LeetCode" ,
66- } ) , "ROOT" , false ) ,
56+ } ) , false ) ,
6757 ] ;
6858 }
6959 if ( ! element ) { // Root view
70- return [
71- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
72- id : Category . Difficulty ,
73- name : Category . Difficulty ,
74- } ) , "ROOT" , false ) ,
75- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
76- id : Category . Tag ,
77- name : Category . Tag ,
78- } ) , "ROOT" , false ) ,
79- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
80- id : Category . Company ,
81- name : Category . Company ,
82- } ) , "ROOT" , false ) ,
83- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
84- id : Category . Favorite ,
85- name : Category . Favorite ,
86- } ) , "ROOT" , false ) ,
87- ] ;
60+ return explorerNodeManager . getRootNodes ( ) ;
8861 } else {
89- switch ( element . name ) { // First-level
62+ switch ( element . id ) { // First-level
9063 case Category . Favorite :
91- const nodes : IProblem [ ] = this . treeData [ Category . Favorite ] ;
92- return nodes . map ( ( p : IProblem ) => new LeetCodeNode ( p , Category . Favorite ) ) ;
64+ return explorerNodeManager . getFavoriteNodes ( ) ;
9365 case Category . Difficulty :
66+ return explorerNodeManager . getAllDifficultyNodes ( ) ;
9467 case Category . Tag :
68+ return explorerNodeManager . getAllTagNodes ( ) ;
9569 case Category . Company :
96- return this . composeSubCategoryNodes ( element ) ;
97- default : // Second and lower levels
98- return element . isProblem ? [ ] : this . composeProblemNodes ( element ) ;
99- }
100- }
101- }
102-
103- private async getProblemData ( ) : Promise < void > {
104- // clear cache
105- this . treeData = {
106- Difficulty : new Map < string , IProblem [ ] > ( ) ,
107- Tag : new Map < string , IProblem [ ] > ( ) ,
108- Company : new Map < string , IProblem [ ] > ( ) ,
109- Favorite : [ ] ,
110- } ;
111- for ( const problem of await list . listProblems ( ) ) {
112- // Add favorite problem, no matter whether it is solved.
113- if ( problem . isFavorite ) {
114- this . treeData [ Category . Favorite ] . push ( problem ) ;
115- }
116- // Hide solved problem in other category.
117- if ( problem . state === ProblemState . AC && getWorkspaceConfiguration ( ) . get < boolean > ( "hideSolved" ) ) {
118- continue ;
70+ return explorerNodeManager . getAllCompanyNodes ( ) ;
71+ default :
72+ if ( element . isProblem ) {
73+ return [ ] ;
74+ }
75+ return explorerNodeManager . getChildrenNodesById ( element . id ) ;
11976 }
120-
121- this . addProblemToTreeData ( problem ) ;
122- }
123- }
124-
125- private composeProblemNodes ( node : LeetCodeNode ) : LeetCodeNode [ ] {
126- const map : Map < string , IProblem [ ] > | undefined = this . treeData [ node . parentName ] ;
127- if ( ! map ) {
128- leetCodeChannel . appendLine ( `Category: ${ node . parentName } is not available.` ) ;
129- return [ ] ;
130- }
131- const problems : IProblem [ ] = map . get ( node . name ) || [ ] ;
132- const problemNodes : LeetCodeNode [ ] = [ ] ;
133- for ( const problem of problems ) {
134- problemNodes . push ( new LeetCodeNode ( problem , node . name ) ) ;
13577 }
136- return problemNodes ;
137- }
138-
139- private composeSubCategoryNodes ( node : LeetCodeNode ) : LeetCodeNode [ ] {
140- const category : Category = node . name as Category ;
141- if ( category === Category . Favorite ) {
142- leetCodeChannel . appendLine ( "No sub-level for Favorite nodes" ) ;
143- return [ ] ;
144- }
145- const map : Map < string , IProblem [ ] > | undefined = this . treeData [ category ] ;
146- if ( ! map ) {
147- leetCodeChannel . appendLine ( `Category: ${ category } is not available.` ) ;
148- return [ ] ;
149- }
150- return this . getSubCategoryNodes ( map , category ) ;
15178 }
15279
15380 private parseIconPathFromProblemState ( element : LeetCodeNode ) : string {
@@ -171,16 +98,16 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
17198
17299 private getSubCategoryTooltip ( element : LeetCodeNode ) : string {
173100 // return '' unless it is a sub-category node
174- if ( element . isProblem || ! this . treeData [ element . parentName ] ) {
101+ if ( element . isProblem || element . id === "ROOT" || element . id in Category ) {
175102 return "" ;
176103 }
177104
178- const problems : IProblem [ ] = this . treeData [ element . parentName ] . get ( element . id ) ;
105+ const childernNodes : LeetCodeNode [ ] = explorerNodeManager . getChildrenNodesById ( element . id ) ;
179106
180107 let acceptedNum : number = 0 ;
181108 let failedNum : number = 0 ;
182- for ( const prob of problems ) {
183- switch ( prob . state ) {
109+ for ( const node of childernNodes ) {
110+ switch ( node . state ) {
184111 case ProblemState . AC :
185112 acceptedNum ++ ;
186113 break ;
@@ -195,73 +122,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
195122 return [
196123 `AC: ${ acceptedNum } ` ,
197124 `Failed: ${ failedNum } ` ,
198- `Total: ${ problems . length } ` ,
125+ `Total: ${ childernNodes . length } ` ,
199126 ] . join ( os . EOL ) ;
200127 }
201-
202- private addProblemToTreeData ( problem : IProblem ) : void {
203- this . putProblemToMap ( this . treeData . Difficulty , problem . difficulty , problem ) ;
204- for ( const tag of problem . tags ) {
205- this . putProblemToMap ( this . treeData . Tag , _ . startCase ( tag ) , problem ) ;
206- }
207- for ( const company of problem . companies ) {
208- this . putProblemToMap ( this . treeData . Company , _ . startCase ( company ) , problem ) ;
209- }
210- }
211-
212- private putProblemToMap ( map : Map < string , IProblem [ ] > , key : string , problem : IProblem ) : void {
213- const problems : IProblem [ ] | undefined = map . get ( key ) ;
214- if ( problems ) {
215- problems . push ( problem ) ;
216- } else {
217- map . set ( key , [ problem ] ) ;
218- }
219- }
220-
221- private getSubCategoryNodes ( map : Map < string , IProblem [ ] > , category : Category ) : LeetCodeNode [ ] {
222- const subCategoryNodes : LeetCodeNode [ ] = Array . from ( map . keys ( ) ) . map ( ( subCategory : string ) => {
223- return new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
224- id : subCategory ,
225- name : subCategory ,
226- } ) , category . toString ( ) , false ) ;
227- } ) ;
228- this . sortSubCategoryNodes ( subCategoryNodes , category ) ;
229- return subCategoryNodes ;
230- }
231-
232- private sortSubCategoryNodes ( subCategoryNodes : LeetCodeNode [ ] , category : Category ) : void {
233- switch ( category ) {
234- case Category . Difficulty :
235- subCategoryNodes . sort ( ( a : LeetCodeNode , b : LeetCodeNode ) : number => {
236- function getValue ( input : LeetCodeNode ) : number {
237- switch ( input . name . toLowerCase ( ) ) {
238- case "easy" :
239- return 1 ;
240- case "medium" :
241- return 2 ;
242- case "hard" :
243- return 3 ;
244- default :
245- return Number . MAX_SAFE_INTEGER ;
246- }
247- }
248- return getValue ( a ) - getValue ( b ) ;
249- } ) ;
250- break ;
251- case Category . Tag :
252- case Category . Company :
253- subCategoryNodes . sort ( ( a : LeetCodeNode , b : LeetCodeNode ) : number => {
254- if ( a . name === "Unknown" ) {
255- return 1 ;
256- } else if ( b . name === "Unknown" ) {
257- return - 1 ;
258- } else {
259- return Number ( a . name > b . name ) - Number ( a . name < b . name ) ;
260- }
261- } ) ;
262- break ;
263- default :
264- break ;
265- }
266- }
267128}
0 commit comments