Skip to content

Highest region algorithm #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: classes-and-types
Choose a base branch
from
Open
40 changes: 40 additions & 0 deletions src/assets/obviousAnswerSampleData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { EventStream } from '../types';

export const obviousAnswerData: EventStream = [
{
timestamp: 123123123,
eventType: 'newMessage',
},
{
timestamp: 123123124,
eventType: 'newMessage',
},
{
timestamp: 123123125,
eventType: 'screenshot',
},
{
timestamp: 123123126,
eventType: 'screenshot',
},
{
timestamp: 123123127,
eventType: 'screenshot',
},
{
timestamp: 123123128,
eventType: 'screenshot',
},
{
timestamp: 123123129,
eventType: 'screenshot',
},
{
timestamp: 123123130,
eventType: 'newMessage',
},
{
timestamp: 123123131,
eventType: 'newMessage',
}
]
38 changes: 26 additions & 12 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { AppEvent } from './types'
import { Region } from './models/region'
import { retrieveScoreByEventType } from './utils/utils'
import { obviousAnswerData } from './assets/obviousAnswerSampleData'
import { HighestRegionLocator } from './models/highestRegionLocator'

describe('Region', () => {

const appEvent: AppEvent =
{
timestamp: 123123123,
eventType: 'newMessage',
}

it('adds an AppEvent to a region', () => {
const region = new Region()
region.addAppEvent(appEvent)
expect(region.regionEvents.length).toEqual(1)
})
const appEvent: AppEvent[] =
[
{
timestamp: 123123123,
eventType: 'newMessage',
}
]

it('totals up the score of a region', () => {
const region = new Region()
region.addAppEvent(appEvent)
region.regionEvents = appEvent
expect(region.getScore()).toEqual(1)
})
})
Expand All @@ -36,4 +34,20 @@ describe('RetrieveScoreByEventType', () => {
it('provides the correct score for event type: screenshot', () => {
expect(retrieveScoreByEventType('screenshot')).toEqual(3)
})
})

describe('End-to-end EventStream Puzzler', () => {
it('the program should successfully locate the highest scoring region', () => {
// obviousAnswerData is sample data with an obvious answer if the region size is 5
const highestRegionLocator = new HighestRegionLocator(obviousAnswerData)
const regionSize = 5
const highestRegion = highestRegionLocator.locateHighestRegion(regionSize)
expect(highestRegion.getScore()).toEqual(15)
expect(highestRegion.regionEvents.length).toEqual(regionSize)
expect(highestRegion.regionEvents[0].timestamp).toEqual(123123125)
expect(highestRegion.regionEvents[1].timestamp).toEqual(123123126)
expect(highestRegion.regionEvents[2].timestamp).toEqual(123123127)
expect(highestRegion.regionEvents[3].timestamp).toEqual(123123128)
expect(highestRegion.regionEvents[4].timestamp).toEqual(123123129)
})
})
14 changes: 13 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import { sampleData } from './assets/sampleData'
import { HighestRegionLocator } from './models/highestRegionLocator'

const main = () => {
console.log('main is running')
const regionSize = 5

if (sampleData.length < regionSize) {
console.log(`EventStream must contain >= ${regionSize} events`)
} else {
const highestRegionLocator = new HighestRegionLocator(sampleData)
const highestRegion = highestRegionLocator.locateHighestRegion(regionSize)
console.log(`Highest scoring region found with score: ${highestRegion.getScore()}`)
console.log(highestRegion);
}
}

main()
69 changes: 66 additions & 3 deletions src/models/highestRegionLocator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,71 @@ export class HighestRegionLocator {
this.eventStream = eventStream
}

locateHighestRegion(): Region {
throw console.error('This is not implemented yet')
return new Region()
/* locateHighestRegion() Description:
*
* Given an EventStream, locateHighestRegion locates the highest scoring region
* of the EventStream, with the given size of regionSize.
*
* The region represents the highest scoring 'consecutive' events in the given EventStream.
* See src/utils/utils.ts for the scoring associated with each event type.
*
* The algorithm uses a 'sliding window' of size regionSize to calculate the
* score of the events in that region. Each time a higher scoring region, the
* that region is stored in the maxRegion variable. Once the end of the EventStream
* is reached, the highest scoring region is returned.
*
* For example, let 'e' be an event in the EventStream:
*
* e1 |
* e2 |
* e3 | <- first loop looks at these
* e4 | and updates the maxRegion
* e5 | if this region is higher
* e6 than the previous region
* e7
*
* e1
* e2 |
* e3 | <- second loop looks at these
* e4 | and updates the maxRegion
* e5 | if this region is higher
* e6 | than the previous region
* e7
*
*/
locateHighestRegion(regionSize: number): Region {
let streamLength = this.eventStream.length

// The first index to slice off of the eventSream
let startingIndex = 0;

// The highest score calculated so far
let maxScore = 0;

// A temporary region variable used to calculate the current region
let currentRegion = new Region();

// The highest scoring region so far
let maxRegion = new Region();

// Loop over the stream, moving the 'window' by one index each time
while (startingIndex + regionSize < streamLength) {

// slice a subarray from the eventStream
// The current window is determined by the startingIndex + the region size
currentRegion.regionEvents = this.eventStream.slice(startingIndex, startingIndex + regionSize);

// Get the score of the current region and compare it against the max score
let currentScore = currentRegion.getScore();
if (currentScore > maxScore) {
maxScore = currentScore;
maxRegion = currentRegion;
}
// Reset the current region for the next loop
currentRegion = new Region();
// Increment the startingIndex
startingIndex += 1;
}
return maxRegion;
}
}
9 changes: 4 additions & 5 deletions src/models/region.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { AppEvent } from '../types'
export class Region {
regionEvents: AppEvent[] = []

addAppEvent(appEvent: AppEvent): void {
this.regionEvents.push(appEvent)
}

/* getScore() Description:
* Totals the score for each event in this region
*/
getScore(): number {
let totalScore = 0
for (let appEvent of this.regionEvents) {
totalScore += retrieveScoreByEventType(appEvent.eventType)
}
return totalScore
}
}
}