Skip to content

Commit

Permalink
Add exemplar analyzers (#116)
Browse files Browse the repository at this point in the history
* Add exemplar fixtures

* Enable exemplar analyzers

* Remove fruit-picker from list
  • Loading branch information
SleeplessByte committed Sep 4, 2021
1 parent 50a48bf commit 304f89a
Show file tree
Hide file tree
Showing 108 changed files with 6,211 additions and 2 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## 0.16.0

- Add exemplary analyzer for `amusement-park`
- Add exemplary analyzer for `bird-watcher`
- Add exemplary analyzer for `coordinate-transformation`
- Add exemplary analyzer for `elyses-analytic-enchantments`
- Add exemplary analyzer for `elyses-destructured-enchantments`
- Add exemplary analyzer for `elyses-enchantments`
- Add exemplary analyzer for `elyses-looping-enchantments`
- Add exemplary analyzer for `elyses-transformative-enchantments`
- Add exemplary analyzer for `factory-sensors`
- Add exemplary analyzer for `high-score-board`
- Add exemplary analyzer for `lasagna-master`
- Add exemplary analyzer for `lucky-numbers`
- Add exemplary analyzer for `mixed-juices`
- Add exemplary analyzer for `nullability`
- Add exemplary analyzer for `ozans-playlist`
- Add exemplary analyzer for `pizza-order`
- Add exemplary analyzer for `translation-service`
- Add exemplary analyzer for `vehicle-purchase`

## 0.15.0

- Allow non-optimal constants in `resistor-color-duo`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@exercism/javascript-analyzer",
"version": "0.15.0",
"version": "0.16.0",
"description": "Exercism analyzer for javascript",
"repository": "https://github.com/exercism/javascript-analyzer",
"author": "Derk-Jan Karrenbeld <[email protected]>",
Expand Down
27 changes: 27 additions & 0 deletions src/analyzers/Autoload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ function autoload(exercise: Readonly<Exercise>): ReturnType<NodeRequire> {
path.join(__dirname, 'concept', exercise.slug, 'index'),
]

// These exercises can also defer to the exemplar analyzer only
if (
[
'amusement-park',
'bird-watcher',
'coordinate-transformation',
'elyses-analytic-enchantments',
'elyses-destructured-enchantments',
'elyses-enchantments',
'elyses-looping-enchantments',
'elyses-transformative-enchantments',
'factory-sensors',
// 'fruit-picker',
'high-score-board',
'lasagna-master',
'lucky-numbers',
'mixed-juices',
'nullability',
'ozans-playlist',
'pizza-order',
'translation-service',
'vehicle-purchase',
].includes(exercise.slug)
) {
modulePaths.push(path.join(__dirname, 'concept', '__exemplar', 'index'))
}

const results = modulePaths.map((modulePath) => {
try {
return require(modulePath)
Expand Down
62 changes: 62 additions & 0 deletions test/analyzers/__exemplar/exemplar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { DirectoryWithConfigInput } from '@exercism/static-analysis'
import path from 'path'
import { ExemplarAnalyzer } from '~src/analyzers/concept/__exemplar'
import { EXEMPLAR_SOLUTION } from '~src/comments/shared'
import { makeAnalyze, makeOptions } from '~test/helpers/smoke'
;[
'amusement-park',
'bird-watcher',
'coordinate-transformation',
'elyses-analytic-enchantments',
'elyses-destructured-enchantments',
'elyses-enchantments',
'elyses-looping-enchantments',
'elyses-transformative-enchantments',
'factory-sensors',
// 'fruit-picker',
'high-score-board',
'lasagna-master',
'lucky-numbers',
'mixed-juices',
'nullability',
'ozans-playlist',
'pizza-order',
'translation-service',
'vehicle-purchase',
].forEach((exercise) => {
const inputDir = path.join(
__dirname,
'..',
'..',
'fixtures',
exercise,
'exemplar'
)

const analyze = makeAnalyze(
() => new ExemplarAnalyzer(),
makeOptions({
get inputDir(): string {
return inputDir
},
get exercise(): string {
return exercise
},
})
)

describe(`When running analysis on ${exercise}`, () => {
it('recognises the exemplar solution', async () => {
const input = new DirectoryWithConfigInput(inputDir)

const [solution] = await input.read()
const output = await analyze(solution)

expect(output.comments.length).toBe(1)
expect(output.comments[0].type).toBe('celebratory')
expect(output.comments[0].externalTemplate).toBe(
EXEMPLAR_SOLUTION().externalTemplate
)
})
})
})
11 changes: 11 additions & 0 deletions test/fixtures/amusement-park/exemplar/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"blurb": "Learn about undefined and null by managing visitors and tickets at an amusement park.",
"authors": ["junedev"],
"contributors": [],
"files": {
"solution": ["amusement-park.js"],
"test": ["amusement-park.spec.js"],
"exemplar": [".meta/exemplar.js"]
},
"forked_from": ["ruby/amusement-park"]
}
66 changes: 66 additions & 0 deletions test/fixtures/amusement-park/exemplar/.meta/exemplar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/// <reference path="../global.d.ts" />
// @ts-check

/**
* Creates a new visitor.
*
* @param {string} name
* @param {number} age
* @param {string} ticketId
* @returns {Visitor} the visitor that was created
*/
export function createVisitor(name, age, ticketId) {
return { name, age, ticketId };
}

/**
* Revokes a ticket for a visitor.
*
* @param {Visitor} visitor the visitor with an active ticket
* @returns {Visitor} the visitor without a ticket
*/
export function revokeTicket(visitor) {
visitor.ticketId = null;
return visitor;
}

/**
* Determines the status a ticket has in the ticket tracking object.
*
* @param {Record<string, string|null>} tickets
* @param {string} ticketId
* @returns {string} ticket status
*/
export function ticketStatus(tickets, ticketId) {
if (tickets[ticketId] === undefined) {
return 'unknown ticket id';
}

if (tickets[ticketId] === null) {
return 'not sold';
}

return 'sold to ' + tickets[ticketId];
}

/**
* Determines the status a ticket has in the ticket tracking object
* and returns a simplified status message.
*
* @param {Record<string, string|null>} tickets
* @param {string} ticketId
* @returns {string} ticket status
*/
export function simpleTicketStatus(tickets, ticketId) {
return tickets[ticketId] ?? 'invalid ticket !!!';
}

/**
* Determines the version of the GTC that was signed by the visitor.
*
* @param {VisitorWithGtc} visitor
* @returns {string | undefined} version
*/
export function gtcVersion(visitor) {
return visitor.gtc?.version;
}
66 changes: 66 additions & 0 deletions test/fixtures/amusement-park/exemplar/amusement-park.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/// <reference path="./global.d.ts" />
// @ts-check

/**
* Creates a new visitor.
*
* @param {string} name
* @param {number} age
* @param {string} ticketId
* @returns {Visitor} the visitor that was created
*/
export function createVisitor(name, age, ticketId) {
return { name, age, ticketId };
}

/**
* Revokes a ticket for a visitor.
*
* @param {Visitor} visitor the visitor with an active ticket
* @returns {Visitor} the visitor without a ticket
*/
export function revokeTicket(visitor) {
visitor.ticketId = null;
return visitor;
}

/**
* Determines the status a ticket has in the ticket tracking object.
*
* @param {Record<string, string|null>} tickets
* @param {string} ticketId
* @returns {string} ticket status
*/
export function ticketStatus(tickets, ticketId) {
if (tickets[ticketId] === undefined) {
return 'unknown ticket id';
}

if (tickets[ticketId] === null) {
return 'not sold';
}

return 'sold to ' + tickets[ticketId];
}

/**
* Determines the status a ticket has in the ticket tracking object
* and returns a simplified status message.
*
* @param {Record<string, string|null>} tickets
* @param {string} ticketId
* @returns {string} ticket status
*/
export function simpleTicketStatus(tickets, ticketId) {
return tickets[ticketId] ?? 'invalid ticket !!!';
}

/**
* Determines the version of the GTC that was signed by the visitor.
*
* @param {VisitorWithGtc} visitor
* @returns {string | undefined} version
*/
export function gtcVersion(visitor) {
return visitor.gtc?.version;
}
Loading

0 comments on commit 304f89a

Please sign in to comment.