11 lines
27 KiB
JSON
Raw Normal View History

2025-01-10 23:59:09 +00:00
{
"extension": ".js",
"source": "\n\n\nfunction randInt(min, max) {\n min = Math.ceil(min);\n max = Math.floor(max);\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\nfunction cssRuleExists(match){\n for(let i = 0; i < document.styleSheets.length; i++){\n let styleSheet = document.styleSheets[i]\n let rules = styleSheet.cssRules\n for(let j = 0; j < rules.length; j++){\n let rule = rules[j]\n if(rule.selectorText && rule.selectorText == match){\n return true;\n }\n }\n }\n return false\n}\n\nclass EventHandler {\n constructor() {\n this.events = {};\n this.eventCount = 0;\n this.suppresEvents = false;\n this.debugEvents = false;\n }\n on(event, listener) {\n if (!this.events[event]) {\n this.events[event] = { name:name, listeners: [],callCount: 0};\n }\n this.events[event].listeners.push(listener);\n }\n off(event, listenerToRemove) {\n if (!this.events[event]) return;\n this.events[event].listeners = this.events[event].listeners.filter(listener => listener !== listenerToRemove);\n }\n emit(event, data) {\n if (!this.events[event]) return [];\n if (this.suppresEvents) return [];\n this.eventCount++;\n const returnValue = this.events[event].listeners.map(listener =>{\n var returnValue = listener(data)\n if(returnValue == undefined)\n return null\n return returnValue\n });\n this.events[event].callCount++;\n if(this.debugEvents){\n console.debug('debugEvent',{event:event, arg:data, callCount: this.events[event].callCount, number:this.eventCount, returnValues:returnValue})\n }\n return returnValue\n }\n suppres(fn) {\n const originallySuppressed = this.suppresEvents\n this.suppresEvents = true \n fn(this)\n this.suppresEvents = originallySuppressed\n return originallySuppressed\n }\n}\n\n\nclass Col extends EventHandler {\n id = 0\n values = []\n initial = false\n _marked = false\n row = null\n index = 0\n valid = true\n _selected = false\n _value = 0\n _isValidXy() {\n if (!this._value)\n return true;\n return this.row.puzzle.fields.filter(field => {\n return (\n field.index == this.index && field.value == this._value\n ||\n field.row.index == this.row.index && field.value == this._value)\n\n }).filter(field => field != this).length == 0\n }\n mark() {\n this.marked = true \n }\n unmark() {\n this.marked = false\n }\n select() {\n this.selected = true\n }\n unselect() {\n this.selected = false\n }\n _isValidBox() {\n if (!this._value)\n return true;\n let startRow = this.row.index - this.row.index % (this.row.puzzle.size / 3);\n let startCol = this.index - this.index % (this.row.puzzle.size / 3);\n for (let i = 0; i < this.row.puzzle.size / 3; i++) {\n for (let j = 0; j < this.row.puzzle.size / 3; j++) {\n const field = this.row.puzzle.get(i + startRow, j + startCol);\n if (field != this && field.value == this._value) {\n return false;\n }\n }\n }\n return true\n }\n validate() {\n if (!this.row.puzzle.initalized) {\n return this.valid;\n }\n if (this.initial) {\n this.valid = true\n return this.valid\n }\n if (!this.value && !this.valid) {\n this.valid = true\n this.emit('update', this)\n return this.valid\n }\n let oldValue = this.valid\n this.valid = this._isValidXy() && this._isValidBox();\n if (oldValue != this.valid) {\n this.emit('update', this)\n }\n return this.valid\n }\n set value(val) {\n
"review": "# Grade: 6\n\n## Bugs\n- There are several typos and inconsistencies, e.g., the use of both `initalized` and `initialized`.\n- The `suppresEvents` property is not correctly spelt; it should be `suppressEvents`.\n- The method `_isValidXy` contains overlapping conditions which could be logically simplified.\n- The `makeInvalid` method references an `app` object that is not defined within this context.\n- Use of `document.styleSheets` in `cssRuleExists` fails due to potential security restrictions on cross-origin stylesheets.\n- Inconsistent use of `null` vs `undefined` in return values.\n\n## Optimizations\n- Use parameters validation more thoroughly, such as checking for valid inputs in `randInt`.\n- The naming convention could be improved for understandability and consistency, e.g., `suppres` function.\n- Repeated code, such as filtering methods, can be refactored for optimization, like combining filter operations.\n- Use modern ES6+ features, such as default parameters, Spread or Rest operators or ES6 modules, to streamline the code.\n- Better management of state could be achieved through a state management solution or library.\n- Reduce use of `console.debug` and replace with conditional logging through feature toggles.\n- Use a consistent naming convention for properties and methods (e.g., camelCase).\n- Optimize the reactivity in updating UI elements to avoid unnecessary re-renders.\n\n## Good points\n- Modularity by using classes like `Puzzle`, `Row`, and `Col` provides a good separation of concerns.\n- Use of event handling demonstrates a comprehension of the JavaScript event system.\n- `Sudoku` component as a custom HTML element shows an understanding of modern web technologies.\n- Clear intention for a large part of the code logic supporting a Sudoku game, showing substantial problem domain knowledge.\n\n## Summary\nThe code represents a good attempt at creating a Sudoku-like game with extendable and maintainable constructs using custom elements and modular JavaScript. However, it suffers from certain inconsistencies and potential bugs which can lead to execution errors. Code optimization techniques could be applied to increase performance and maintainability, and to fix some of the identified issues. Thoughtful comments and clearer naming can enhance code readability and understandability. \n\n## Open source alternatives\n- [SudokuJS](https://github.com/robatron/sudoku.js) \n- [js-sudoku](https://github.com/robatron/sudoku.js/)\n- [sudoku-generator](https://github.com/robatron/sudoku.js/)",
"filename": "sudoku.js",
"path": "sudoku.js",
"directory": "",
"grade": 6,
"size": 23740,
"line_count": 843
}