Initial commit

This commit is contained in:
2025-08-28 22:38:53 +02:00
commit f15208fe6d
232 changed files with 16821 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
package ch.gtache.fro;
/**
* Represents a bird
*/
@FunctionalInterface
public interface Bird {
/**
* Returns the name of the bird
*
* @return The name
*/
String name();
}

View File

@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* {@link Provider} of {@link Bird}
*/
public interface BirdProvider extends Provider<Bird> {
}

View File

@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* Translates a {@link Bird} to a string
*/
public interface BirdTranslator extends Translator<Bird> {
}

View File

@@ -0,0 +1,71 @@
package ch.gtache.fro;
import ch.gtache.fro.practice.BirdPracticeParameters;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Collection;
public interface Configuration {
/**
* Returns the root folder where the data is stored
*
* @return The root folder
*/
Path rootFolder();
/**
* Sets the root folder where the data is stored
*
* @param rootFolder The root folder
*/
void setRootFolder(final Path rootFolder);
/**
* Returns the duration to wait between two fetches
*
* @return The duration
*/
Duration waitBetweenFetch();
/**
* Sets the duration to wait between two fetches
*
* @param waitBetweenFetch The duration
*/
void setWaitBetweenFetch(final Duration waitBetweenFetch);
/**
* Returns the bird practice parameters
*
* @return The parameters
*/
Collection<BirdPracticeParameters> birdPracticeParameters();
/**
* Returns the bird practice parameters for a specific bird
*
* @param bird The bird
* @return The parameters
*/
BirdPracticeParameters birdPracticeParameters(final Bird bird);
/**
* Sets the bird practice parameters
*
* @param birdPracticeParameters The parameters
*/
default void setBirdPracticeParameters(final Collection<? extends BirdPracticeParameters> birdPracticeParameters) {
for (final var birdPracticeParameter : birdPracticeParameters) {
setBirdPracticeParameters(birdPracticeParameter);
}
}
/**
* Sets the bird practice parameters for a specific bird
*
* @param birdPracticeParameters The parameters
*/
void setBirdPracticeParameters(final BirdPracticeParameters birdPracticeParameters);
}

View File

@@ -0,0 +1,35 @@
package ch.gtache.fro;
/**
* Exception thrown by {@link Fetcher}
*/
public class FetchException extends Exception {
/**
* Instantiates the exception
*
* @param message The message
*/
public FetchException(final String message) {
super(message);
}
/**
* Instantiates the exception
*
* @param message The message
* @param cause The cause
*/
public FetchException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Instantiates the exception
*
* @param cause The cause
*/
public FetchException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,66 @@
package ch.gtache.fro;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/**
* Fetches bird data from a source
*/
public interface Fetcher {
/**
* Returns the name of the fetcher
*
* @return The name
*/
String name();
/**
* Fetches all the birds
*
* @return The filled birds
* @throws FetchException If an error occurs
*/
List<FilledBird> fetchAll() throws FetchException;
/**
* Fetches all the birds asynchronously
*
* @return A future with the filled birds
*/
default CompletableFuture<List<FilledBird>> fetchAllAsync() {
return CompletableFuture.supplyAsync(() -> {
try {
return fetchAll();
} catch (final FetchException e) {
throw new CompletionException(e);
}
});
}
/**
* Fetches a bird
*
* @param bird The bird
* @return The filled bird
* @throws FetchException If an error occurs
*/
FilledBird fetch(Bird bird) throws FetchException;
/**
* Fetches a bird asynchronously
*
* @param bird The bird
* @return A future with the filled bird
*/
default CompletableFuture<FilledBird> fetchAsync(final Bird bird) {
return CompletableFuture.supplyAsync(() -> {
try {
return fetch(bird);
} catch (final FetchException e) {
throw new CompletionException(e);
}
});
}
}

View File

@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* {@link Provider} of {@link Fetcher}
*/
public interface FetcherProvider extends Provider<Fetcher> {
}

View File

@@ -0,0 +1,30 @@
package ch.gtache.fro;
import java.util.Collection;
/**
* Represents a bird with its pictures and sounds
*/
public interface FilledBird {
/**
* Returns the bird
*
* @return The bird
*/
Bird bird();
/**
* Returns the pictures
*
* @return The pictures
*/
Collection<Picture> pictures();
/**
* Returns the sounds
*
* @return The sounds
*/
Collection<Sound> sounds();
}

View File

@@ -0,0 +1,30 @@
package ch.gtache.fro;
import java.nio.file.Path;
/**
* Represents a bird picture
*/
public interface Picture {
/**
* Returns the bird
*
* @return The bird
*/
Bird bird();
/**
* Returns the picture type
*
* @return The picture type
*/
PictureType type();
/**
* Returns the path to the picture
*
* @return The path
*/
Path path();
}

View File

@@ -0,0 +1,72 @@
package ch.gtache.fro;
/**
* Represents the type of bird picture
*/
public enum PictureType {
/**
* Male nuptial adult
*/
ADULT_NUPTIAL_MALE,
/**
* Female nuptial adult
*/
ADULT_NUPTIAL_FEMALE,
/**
* Nuptial adult (in case there is no difference between male and female)
*/
ADULT_NUPTIAL,
/**
* Male internuptial adult
*/
ADULT_INTERNUPTIAL_MALE,
/**
* Female internuptial adult
*/
ADULT_INTERNUPTIAL_FEMALE,
/**
* Internuptial adult (in case there is no difference between male and female)
*/
ADULT_INTERNUPTIAL,
/**
* Male adult (in case there is no difference between nuptial and internuptial)
*/
ADULT_MALE,
/**
* Female adult (in case there is no difference between nuptial and internuptial)
*/
ADULT_FEMALE,
/**
* Adult (in case there is no difference between male and female and nuptial and internuptial)
*/
ADULT,
/**
* Juvenile male
*/
JUVENILE_MALE,
/**
* Juvenile female
*/
JUVENILE_FEMALE,
/**
* Juvenile (in case there is no difference between male and female)
*/
JUVENILE,
/**
* For varying species, the light morph
*/
LIGHT_MORPH,
/**
* For varying species, the dark morph
*/
DARK_MORPH,
/**
* For varying species, the sub species
*/
SUB_SPECIES,
/**
* Unknown
*/
UNKNOWN
}

View File

@@ -0,0 +1,10 @@
package ch.gtache.fro;
/**
* Translates a {@link PictureType} to a string
*/
@FunctionalInterface
public interface PictureTypeTranslator extends Translator<PictureType> {
}

View File

@@ -0,0 +1,59 @@
package ch.gtache.fro;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/**
* Provides objects
*/
public interface Provider<T> {
/**
* Returns the object with the given name
*
* @param name The name of the object
* @return The object, or null if not found
* @throws ProvisionException If an error occurs
*/
T getObject(final String name) throws ProvisionException;
/**
* Returns the object with the given name asynchronously
*
* @param name The name of the object
* @return A future containing the object, or null if not found
*/
default CompletableFuture<T> getObjectAsync(final String name) {
return CompletableFuture.supplyAsync(() -> {
try {
return getObject(name);
} catch (final ProvisionException e) {
throw new CompletionException(e);
}
});
}
/**
* Returns all the object known to this provider
*
* @return The list of object
* @throws ProvisionException If an error occurs
*/
Collection<T> getAllObjects() throws ProvisionException;
/**
* Returns all the object known to this provider asynchronously
*
* @return A future containing the list of object
*/
default CompletableFuture<Collection<T>> getAllObjectsAsync() {
return CompletableFuture.supplyAsync(() -> {
try {
return getAllObjects();
} catch (final ProvisionException e) {
throw new CompletionException(e);
}
});
}
}

View File

@@ -0,0 +1,35 @@
package ch.gtache.fro;
/**
* Exception thrown by providers
*/
public class ProvisionException extends Exception {
/**
* Instantiates the exception
*
* @param message The message
*/
public ProvisionException(final String message) {
super(message);
}
/**
* Instantiates the exception
*
* @param message The message
* @param cause The cause
*/
public ProvisionException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Instantiates the exception
*
* @param cause The cause
*/
public ProvisionException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,30 @@
package ch.gtache.fro;
import java.nio.file.Path;
/**
* Represents a bird sound
*/
public interface Sound {
/**
* Returns the bird
*
* @return The bird
*/
Bird bird();
/**
* Returns the sound type
*
* @return The sound type
*/
SoundType type();
/**
* Returns the path to the sound
*
* @return The path
*/
Path path();
}

View File

@@ -0,0 +1,31 @@
package ch.gtache.fro;
/**
* Represents the type of bird sound
*/
public enum SoundType {
/**
* Sound made by the bird when singing
*/
SONG,
/**
* Sound made by the bird when calling
*/
CALL,
/**
* Sound made by the bird when making an alarm call
*/
ALARM,
/**
* Sound made by the bird when making a fly call
*/
FLY_CALL,
/**
* Sound made by a juvenile bird when making a call
*/
JUVENILE_CALL,
/**
* Unknown
*/
UNKNOWN
}

View File

@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* Translates a {@link SoundType} to a string
*/
public interface SoundTypeTranslator extends Translator<SoundType> {
}

View File

@@ -0,0 +1,35 @@
package ch.gtache.fro;
/**
* Exception thrown by translators
*/
public class TranslationException extends Exception {
/**
* Instantiates the exception
*
* @param message The message
*/
public TranslationException(final String message) {
super(message);
}
/**
* Instantiates the exception
*
* @param message The message
* @param cause The cause
*/
public TranslationException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Instantiates the exception
*
* @param cause The cause
*/
public TranslationException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,60 @@
package ch.gtache.fro;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/**
* Translates objects
*/
@FunctionalInterface
public interface Translator<T> {
/**
* Translates the given object
*
* @param object The object
* @param locale The locale to translate to
* @return The translated string
* @throws TranslationException If an error occurs
*/
String translate(T object, Locale locale) throws TranslationException;
/**
* Translates the given object asynchronously
*
* @param object The object
* @param locale The locale to translate to
* @return A future containing the translated string
*/
default CompletableFuture<String> translateAsync(final T object, final Locale locale) {
return CompletableFuture.supplyAsync(() -> {
try {
return translate(object, locale);
} catch (final TranslationException e) {
throw new CompletionException(e);
}
});
}
/**
* Translates the given object using the default locale
*
* @param object The object
* @return The translated string
* @throws TranslationException If an error occurs
*/
default String translate(final T object) throws TranslationException {
return translate(object, Locale.getDefault());
}
/**
* Translates the given object using the default locale asynchronously
*
* @param object The object
* @return A future containing the translated string
*/
default CompletableFuture<String> translateAsync(final T object) {
return translateAsync(object, Locale.getDefault());
}
}

View File

@@ -0,0 +1,48 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import ch.gtache.fro.PictureType;
import ch.gtache.fro.SoundType;
import java.util.Set;
/**
* Represents the parameters for a bird practice session
*/
public interface BirdPracticeParameters {
/**
* Returns the bird
*
* @return The bird
*/
Bird bird();
/**
* Returns whether this bird is enabled
*
* @return Whether this bird is enabled
*/
boolean enabled();
/**
* Returns the fetchers enabled for this bird
*
* @return The enabled fetcher names
*/
Set<String> enabledFetchers();
/**
* Returns all the picture types that are enabled for this bird
*
* @return The picture types that are enabled
*/
Set<PictureType> enabledPictureTypes();
/**
* Returns all the sound types that are enabled for this bird
*
* @return The sound types that are enabled
*/
Set<SoundType> enabledSoundTypes();
}

View File

@@ -0,0 +1,18 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import java.util.List;
/**
* Represents a multichoice practice question
*/
public interface MultichoicePracticeQuestion extends PracticeQuestion {
/**
* Returns the choices for this question
*
* @return The choices
*/
List<Bird> choices();
}

View File

@@ -0,0 +1,7 @@
package ch.gtache.fro.practice;
/**
* Represents a picture multichoice practice question
*/
public interface PictureMultichoicePracticeQuestion extends PicturePracticeQuestion, MultichoicePracticeQuestion {
}

View File

@@ -0,0 +1,23 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import ch.gtache.fro.Picture;
/**
* Represents a picture practice question
*/
public interface PicturePracticeQuestion extends PracticeQuestion {
/**
* Returns the picture of this question
*
* @return The picture
*/
Picture picture();
@Override
default Bird bird() {
return picture().bird();
}
}

View File

@@ -0,0 +1,39 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import java.util.Map;
/**
* Represents the parameters for a practice session
*/
public interface PracticeParameters {
/**
* Returns the mapping of bird to bird parameters
*
* @return The mapping of bird to bird parameters
*/
Map<Bird, BirdPracticeParameters> birdParameters();
/**
* Returns the practice type
*
* @return The practice type
*/
PracticeType practiceType();
/**
* Returns the number of questions in this practice
*
* @return The number of questions
*/
int questionsCount();
/**
* Returns the number of propositions for a multichoice type
*
* @return The number of propositions
*/
int propositionsCount();
}

View File

@@ -0,0 +1,16 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
/**
* Represents a practice question
*/
public interface PracticeQuestion {
/**
* Returns the correct bird of this question
*
* @return The bird
*/
Bird bird();
}

View File

@@ -0,0 +1,16 @@
package ch.gtache.fro.practice;
/**
* Generates practice questions
*/
@FunctionalInterface
public interface PracticeQuestionGenerator {
/**
* Generates a practice question
*
* @param parameters The practice parameters
* @return The generated practice question
*/
PracticeQuestion generate(final PracticeParameters parameters);
}

View File

@@ -0,0 +1,23 @@
package ch.gtache.fro.practice;
import java.util.List;
/**
* Represents the result of a practice run
*/
public interface PracticeResult {
/**
* Returns the correct questions
*
* @return The correct questions
*/
List<PracticeQuestion> correctQuestions();
/**
* Returns the failed questions
*
* @return The failed questions
*/
List<PracticeQuestion> failedQuestions();
}

View File

@@ -0,0 +1,44 @@
package ch.gtache.fro.practice;
import java.util.List;
/**
* Represents a practice run
*/
public interface PracticeRun {
/**
* Returns the parameters for this run
*
* @return The parameters
*/
PracticeParameters parameters();
/**
* Returns the current question index
*
* @return The question index
*/
int currentQuestionIndex();
/**
* Returns the current question
*
* @return The question
*/
PracticeQuestion currentQuestion();
/**
* Returns the correct questions
*
* @return The correct questions
*/
List<PracticeQuestion> correctQuestions();
/**
* Returns the failed questions
*
* @return The failed questions
*/
List<PracticeQuestion> failedQuestions();
}

View File

@@ -0,0 +1,34 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
/**
* Runs a practice session
*/
public interface PracticeRunner {
/**
* Starts a practice run
*
* @param parameters The practice parameters
* @return The practice run
*/
PracticeRun start(PracticeParameters parameters);
/**
* Runs a step in the practice run
*
* @param run The run
* @param answer The answer
* @return The run after the step
*/
PracticeRun step(PracticeRun run, Bird answer);
/**
* Finishes the practice run
*
* @param run The run
* @return The result of the run
*/
PracticeResult finish(PracticeRun run);
}

View File

@@ -0,0 +1,27 @@
package ch.gtache.fro.practice;
/**
* Represents the type of practice
*/
public enum PracticeType {
/**
* See an image, must write the bird name
*/
PICTURE_EXACT,
/**
* See an image, can choose between multiple birds
*/
PICTURE_MULTICHOICE,
/**
* Hear a sound, must write the bird name
*/
SOUND_EXACT,
/**
* Hear a sound, can choose between multiple birds
*/
SOUND_MULTICHOICE,
/**
* Hear a sound, can choose between multiple bird images
*/
SOUND_MULTICHOICE_PICTURE
}

View File

@@ -0,0 +1,10 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Translator;
/**
* Translates a {@link PracticeType} to a string
*/
public interface PracticeTypeTranslator extends Translator<PracticeType> {
}

View File

@@ -0,0 +1,24 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import ch.gtache.fro.Picture;
import java.util.List;
/**
* Represents a sound multichoice picture practice question
*/
public interface SoundMultichoicePicturePracticeQuestion extends SoundPracticeQuestion, MultichoicePracticeQuestion {
/**
* Returns the choices for this question
*
* @return The choices
*/
List<Picture> pictureChoices();
@Override
default List<Bird> choices() {
return pictureChoices().stream().map(Picture::bird).toList();
}
}

View File

@@ -0,0 +1,8 @@
package ch.gtache.fro.practice;
/**
* Represents a sound multichoice practice question
*/
public interface SoundMultichoicePracticeQuestion extends SoundPracticeQuestion, MultichoicePracticeQuestion {
}

View File

@@ -0,0 +1,23 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import ch.gtache.fro.Sound;
/**
* Represents a sound practice question
*/
public interface SoundPracticeQuestion extends PracticeQuestion {
/**
* Returns the sound of this question
*
* @return The sound
*/
Sound sound();
@Override
default Bird bird() {
return sound().bird();
}
}

View File

@@ -0,0 +1,7 @@
/**
* API module for the FRO project
*/
module ch.gtache.fro.api {
exports ch.gtache.fro;
exports ch.gtache.fro.practice;
}