Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### Gradle files ###
.gradle/
build/
!gradle-wrapper.jar
!gradle-wrapper.properties

### IntelliJ IDEA files ###
.idea/
*.iml
*.iws
*.ipr

### OS-specific files ###
.DS_Store
Thumbs.db

### Log files ###
*.log

### Temporary files ###
*.swp
*.swo
*.bak

### Gradle Wrapper ###
gradle-wrapper.jar
gradle-wrapper.properties

### Compiled class files ###
*.class

### JetBrains Rider ###
.idea/.idea_modules/

### IntelliJ project files ###
out/
22 changes: 12 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ apply plugin: 'eclipse'
version = '1.0-SNAPSHOT'
group = 'org.suggs.interviews.berlinclock'

task wrapper(type: Wrapper){
wrapper {
description = 'Generates gradlew scripts for NIX and win envs'
gradleVersion = '2.0'
gradleVersion = '7.3'
}

repositories {
jcenter()
mavenCentral()
}

Expand All @@ -22,15 +21,18 @@ idea.module {
}

dependencies {
compile 'org.slf4j:slf4j-api:1.7.5',
implementation 'org.slf4j:slf4j-api:1.7.5',
'commons-lang:commons-lang:2.6'

runtime 'org.slf4j:slf4j-log4j12:1.7.5',
implementation 'org.slf4j:slf4j-log4j12:1.7.5',
'log4j:log4j:1.2.17'

testCompile 'junit:junit:4.11',
'org.mockito:mockito-core:1.9.5',
'org.assertj:assertj-core:1.6.1',
'commons-io:commons-io:2.4',
'org.jbehave:jbehave-core:3.8'
testImplementation 'org.mockito:mockito-core:5.15.2',
'org.assertj:assertj-core:3.27.3',
'commons-io:commons-io:2.18.0',
'org.jbehave:jbehave-core:5.2.0'
// Jupiter api and engine dependencies
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'

}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
12 changes: 6 additions & 6 deletions instructions/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ apply plugin: 'eclipse'
version = '1.0-SNAPSHOT'
group = 'org.suggs.interviews.example'

task wrapper(type: Wrapper){
wrapper {
description = 'Generates gradlew scripts for NIX and win envs'
gradleVersion = '2.0'
gradleVersion = '7.3'
}

repositories {
jcenter()
mavenCentral()
mavenLocal()
}

Expand All @@ -22,10 +22,10 @@ idea.module {
}

dependencies {
compile 'org.slf4j:slf4j-api:1.7.5'
implementation 'org.slf4j:slf4j-api:1.7.5'

runtime 'org.slf4j:slf4j-log4j12:1.7.5',
implementation 'org.slf4j:slf4j-log4j12:1.7.5',
'log4j:log4j:1.2.17'

testCompile 'junit:junit:4.11'
testImplementation 'junit:junit:4.11'
}
2 changes: 1 addition & 1 deletion instructions/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
2 changes: 1 addition & 1 deletion instructions/src/test/resources/log4j.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">

<log4j:configuration>

Expand Down
89 changes: 89 additions & 0 deletions src/main/java/com/ubs/opsit/interviews/BerlinClock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.ubs.opsit.interviews;

import java.util.Objects;

/**
* @author Pankaj
*/
public class BerlinClock implements TimeConverter {
@Override
public String convertTime(String time) {
if (time == null || time.isEmpty()) {
throw new IllegalArgumentException("Invalid time format");
}

// Handle invalid time format
String[] values = time.split(":");
if (values.length != 3) {
throw new IllegalArgumentException("Invalid time format");
}

try {
int hours = Integer.parseInt(values[0]);
int minutes = Integer.parseInt(values[1]);
int seconds = Integer.parseInt(values[2]);

// Validate hours, minutes, and seconds range
if (hours < 0 || hours > 24 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59) {
throw new IllegalArgumentException("Invalid time format");
}

// If hours == 24, check if minutes and seconds are 00
if (hours == 24 && (minutes != 0 || seconds != 0)) {
throw new IllegalArgumentException("Invalid time format");
}

// Construct the Berlin Clock string
return getLampOnOff(seconds) + " " + getHours(hours) + " " + getMinutes(minutes);

} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid time format");
}
}


/**
* Every 2 seconds lamp 1st row blinks on/off
* @param seconds
* @return
*/
protected String getLampOnOff(int seconds) {
return seconds % 2 == 0 ? LampSymbol.Y.name() : LampSymbol.O.name();
}

protected String getHours(int hours) {
int numberTopHourLamps = hours / 5;
int numberBottomHourLamps = hours % 5;

return getLampRow(4, numberTopHourLamps, LampSymbol.R) + " " + getLampRow(4, numberBottomHourLamps, LampSymbol.R);
}

protected String getMinutes(int minutes) {
int numberTopMinutesLamps = minutes / 5;
int numberBottomMinutesLamps = minutes % 5;

StringBuilder sb = new StringBuilder();

for (int i = 1; i <= 11; i++) {
sb.append(i <= numberTopMinutesLamps ? getMinuteLampColour(i) : LampSymbol.O.name());
}

sb.append(" ");

sb.append(getLampRow(4, numberBottomMinutesLamps, LampSymbol.Y));

return sb.toString();
}

private String getLampRow(int totalNumberLamps, int numberLampsOn, LampSymbol lampSymbol) {
StringBuilder sb = new StringBuilder(totalNumberLamps);
for (int i = 0; i < totalNumberLamps; i++) {
sb.append(i < numberLampsOn ? lampSymbol : LampSymbol.O.name());
}
return sb.toString();
}

private String getMinuteLampColour(int index) {
return index % 3 == 0 ? LampSymbol.R.name() : LampSymbol.Y.name();
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/ubs/opsit/interviews/BerlinClockMain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ubs.opsit.interviews;

public class BerlinClockMain {

public static void main(String[] args) {
BerlinClock clock = new BerlinClock();
//clock.convertTime("");
//clock.convertTime("23.59.59");
String result = clock.convertTime("23:59:59");
System.out.println(result);

}
}
10 changes: 10 additions & 0 deletions src/main/java/com/ubs/opsit/interviews/LampSymbol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.ubs.opsit.interviews;

/**
* @author Pankaj
*/
public enum LampSymbol {
O,
Y,
R;
}
25 changes: 20 additions & 5 deletions src/test/java/com/ubs/opsit/interviews/BerlinClockFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import static com.ubs.opsit.interviews.support.BehaviouralTestEmbedder.aBehaviouralTestRunner;
import static org.assertj.core.api.Assertions.assertThat;

/**
* Acceptance test class that uses the JBehave (Gerkin) syntax for writing stories. You should not need to
* edit this class to complete the exercise, this is your definition of done.
*/
public class BerlinClockFixture {

private TimeConverter berlinClock;
private TimeConverter berlinClock = new BerlinClock(); // Initialize BerlinClock
private String theTime;

@Test
public void berlinClockAcceptanceTests() throws Exception {
aBehaviouralTestRunner()
.usingStepsFrom(this)
.withStory("berlin-clock.story")
.withStory("berlin-clock.story") // The story file that contains scenarios
.run();
}

Expand All @@ -31,6 +31,21 @@ public void whenTheTimeIs(String time) {

@Then("the clock should look like $")
public void thenTheClockShouldLookLike(String theExpectedBerlinClockOutput) {
assertThat(berlinClock.convertTime(theTime)).isEqualTo(theExpectedBerlinClockOutput);
try {
String result = berlinClock.convertTime(theTime);
Assertions.assertEquals(theExpectedBerlinClockOutput, result);
} catch (IllegalArgumentException e) {
Assertions.assertEquals("Invalid time format", e.getMessage());
}
}

@Then("the clock should throw an error $")
public void thenTheClockShouldThrowAnError(String expectedError) {
try {
berlinClock.convertTime(theTime);
Assertions.fail("Expected error not thrown");
} catch (IllegalArgumentException e) {
Assertions.assertEquals(expectedError, e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.ParameterConverters;
import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
import static org.jbehave.core.reporters.Format.CONSOLE;
import static org.jbehave.core.reporters.Format.HTML;
Expand All @@ -42,7 +42,7 @@ public static BehaviouralTestEmbedder aBehaviouralTestRunner() {
}

@Override
public void run() throws Exception {
public void run() {
List<String> paths = createStoryPaths();
if (paths == null || paths.isEmpty()) {
throw new IllegalStateException("No story paths found for state machine");
Expand All @@ -53,7 +53,7 @@ public void run() throws Exception {

@Override
public InjectableStepsFactory stepsFactory() {
assertThat(stepsFactory).isNotNull();
Assertions.assertNotNull(stepsFactory);
return stepsFactory;
}

Expand All @@ -74,7 +74,7 @@ public BehaviouralTestEmbedder withStory(String aWildcardStoryFilename) {
}

public BehaviouralTestEmbedder usingStepsFrom(Object... stepsSource) {
assertThat(stepsFactory).isNull();
Assertions.assertNull(stepsFactory);
stepsFactory = new InstanceStepsFactory(configuration(), stepsSource);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ubs.opsit.interviews.support;

import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -23,27 +23,27 @@ public final class ClasspathStoryFinder {
private static final Logger LOG = LoggerFactory.getLogger(ClasspathStoryFinder.class);

public static List<String> findFilenamesThatMatch(String aFilenameWithWildcards) {
List<String> filenames = new ArrayList<String>();
List<String> filenames = new ArrayList<>();
for (File file : findFilesThatMatch(aFilenameWithWildcards)) {
filenames.add(file.toURI().toString());
}
return filenames;
}

private static Collection<File> findFilesThatMatch(String aFilenameWithWildcards) {
WildcardFileFilter regexFileFilter = new WildcardFileFilter(aFilenameWithWildcards);
RegexFileFilter regexFileFilter = new RegexFileFilter(aFilenameWithWildcards);
List<File> rootDirsToSearchFrom = getRootDirs();
LOG.info("Searching for stories called [{}] in [{}]", aFilenameWithWildcards, rootDirsToSearchFrom);

List<File> ret = new ArrayList<File>() ;
List<File> ret = new ArrayList<>() ;
for (File f : rootDirsToSearchFrom) {
ret.addAll(listFiles(f, regexFileFilter, DirectoryFileFilter.DIRECTORY)) ;
}
return ret ;
}

private static List<File> getRootDirs() {
List<File> ret = new ArrayList<File>() ;
List<File> ret = new ArrayList<>() ;
try {
Enumeration<URL> roots = ClasspathStoryFinder.class.getClassLoader().getResources("") ;
while(roots.hasMoreElements()) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/log4j.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">

<log4j:configuration>

Expand Down
Loading