Implements database, adds profiles

This commit is contained in:
2025-10-01 22:23:00 +02:00
parent b2571c191f
commit d2da811868
86 changed files with 17323 additions and 483 deletions
+14 -1
View File
@@ -3,7 +3,6 @@ package ch.gtache.fro;
/** /**
* Represents a bird * Represents a bird
*/ */
@FunctionalInterface
public interface Bird { public interface Bird {
/** /**
@@ -12,4 +11,18 @@ public interface Bird {
* @return The name * @return The name
*/ */
String name(); String name();
/**
* Returns the family of the bird
*
* @return The family
*/
BirdFamily family();
/**
* Returns the migration type of the bird
*
* @return The migration type
*/
MigrationType migrationType();
} }
@@ -0,0 +1,15 @@
package ch.gtache.fro;
/**
* Represents a bird family
*/
@FunctionalInterface
public interface BirdFamily {
/**
* Returns the name of the family
*
* @return The name
*/
String name();
}
@@ -0,0 +1,7 @@
package ch.gtache.fro;
/**
* {@link Provider} of {@link BirdFamily}
*/
public interface BirdFamilyProvider extends Provider<String, BirdFamily> {
}
@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* Translates a {@link BirdFamily} to a string
*/
public interface BirdFamilyTranslator extends Translator<BirdFamily> {
}
@@ -3,5 +3,5 @@ package ch.gtache.fro;
/** /**
* {@link Provider} of {@link Bird} * {@link Provider} of {@link Bird}
*/ */
public interface BirdProvider extends Provider<Bird> { public interface BirdProvider extends Provider<String, Bird> {
} }
@@ -3,6 +3,6 @@ package ch.gtache.fro;
/** /**
* {@link Provider} of {@link Fetcher} * {@link Provider} of {@link Fetcher}
*/ */
public interface FetcherProvider extends Provider<Fetcher> { public interface FetcherProvider extends Provider<String, Fetcher> {
} }
@@ -0,0 +1,13 @@
package ch.gtache.fro;
/**
* Interface for initializers
*/
@FunctionalInterface
public interface Initializer {
/**
* Runs the initialization
*/
void initialize();
}
@@ -0,0 +1,15 @@
package ch.gtache.fro;
/**
* Represents a migration type
*/
@FunctionalInterface
public interface MigrationType {
/**
* Returns the name of the type
*
* @return The name
*/
String name();
}
@@ -0,0 +1,7 @@
package ch.gtache.fro;
/**
* {@link Provider} of {@link MigrationType}
*/
public interface MigrationTypeProvider extends Provider<String, MigrationType> {
}
@@ -0,0 +1,8 @@
package ch.gtache.fro;
/**
* Translates a {@link MigrationType} to a string
*/
public interface MigrationTypeTranslator extends Translator<MigrationType> {
}
+13 -10
View File
@@ -6,28 +6,31 @@ import java.util.concurrent.CompletionException;
/** /**
* Provides objects * Provides objects
*
* @param <K> The type of key
* @param <V> The type of value
*/ */
public interface Provider<T> { public interface Provider<K, V> {
/** /**
* Returns the object with the given name * Returns the object with the given key
* *
* @param name The name of the object * @param key The key of the object
* @return The object, or null if not found * @return The object, or null if not found
* @throws ProvisionException If an error occurs * @throws ProvisionException If an error occurs
*/ */
T getObject(final String name) throws ProvisionException; V getObject(final K key) throws ProvisionException;
/** /**
* Returns the object with the given name asynchronously * Returns the object with the given key asynchronously
* *
* @param name The name of the object * @param key The key of the object
* @return A future containing the object, or null if not found * @return A future containing the object, or null if not found
*/ */
default CompletableFuture<T> getObjectAsync(final String name) { default CompletableFuture<V> getObjectAsync(final K key) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
return getObject(name); return getObject(key);
} catch (final ProvisionException e) { } catch (final ProvisionException e) {
throw new CompletionException(e); throw new CompletionException(e);
} }
@@ -40,14 +43,14 @@ public interface Provider<T> {
* @return The list of object * @return The list of object
* @throws ProvisionException If an error occurs * @throws ProvisionException If an error occurs
*/ */
Collection<T> getAllObjects() throws ProvisionException; Collection<V> getAllObjects() throws ProvisionException;
/** /**
* Returns all the object known to this provider asynchronously * Returns all the object known to this provider asynchronously
* *
* @return A future containing the list of object * @return A future containing the list of object
*/ */
default CompletableFuture<Collection<T>> getAllObjectsAsync() { default CompletableFuture<Collection<V>> getAllObjectsAsync() {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
return getAllObjects(); return getAllObjects();
@@ -0,0 +1,38 @@
package ch.gtache.fro;
import java.util.Locale;
import java.util.Map;
/**
* Represents a translated object
*/
@FunctionalInterface
public interface Translated {
/**
* Returns the translations
*
* @return The translations
*/
Map<Locale, String> translations();
/**
* Translates the object using the given locale
*
* @param locale The locale
* @return The translated string
*/
default String translate(final Locale locale) {
return translations().get(locale);
}
/**
* Translates the object using the default locale
*
* @return The translated string
*/
default String translate() {
return translate(Locale.getDefault());
}
}
@@ -45,7 +45,7 @@ public interface Translator<T> {
* @throws TranslationException If an error occurs * @throws TranslationException If an error occurs
*/ */
default String translate(final T object) throws TranslationException { default String translate(final T object) throws TranslationException {
return translate(object, Locale.getDefault()); return translate(object, getDefaultLocale());
} }
/** /**
@@ -55,6 +55,14 @@ public interface Translator<T> {
* @return A future containing the translated string * @return A future containing the translated string
*/ */
default CompletableFuture<String> translateAsync(final T object) { default CompletableFuture<String> translateAsync(final T object) {
return translateAsync(object, Locale.getDefault()); return translateAsync(object, getDefaultLocale());
}
private static Locale normalizeLocale(final Locale locale) {
return Locale.of(locale.getLanguage());
}
private static Locale getDefaultLocale() {
return normalizeLocale(Locale.getDefault());
} }
} }
@@ -0,0 +1,35 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import java.util.Collection;
/**
* Configuration for a practice run
*/
public interface GroupedBirdPracticeParameters {
/**
* Returns the profile of the parameters (if any)
*
* @return The profile
*/
PracticeProfile profile();
/**
* Returns the bird practice parameters
*
* @return The parameters
*/
Collection<BirdPracticeParameters> parameters();
/**
* Returns the bird practice parameters for a specific bird
*
* @param bird The bird
* @return The parameters
*/
default BirdPracticeParameters parameters(final Bird bird) {
return parameters().stream().filter(p -> p.bird().equals(bird)).findFirst().orElse(null);
}
}
@@ -0,0 +1,17 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Provider;
/**
* Manager of {@link GroupedBirdPracticeParameters}s
*/
public interface GroupedBirdPracticeParametersManager extends Provider<PracticeProfile, GroupedBirdPracticeParameters> {
/**
* Saves the given configuration with the given profile
*
* @param configuration The configuration
* @param profile The profile
*/
void save(final GroupedBirdPracticeParameters configuration, final PracticeProfile profile);
}
@@ -1,66 +0,0 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import java.util.Collection;
import java.util.Map;
public interface PracticeConfiguration {
/**
* Sets the number of unsuccessful guesses before a question is considered as failed
*
* @return The number of unsuccessful guesses
*/
int guessesNumber();
/**
* Sets the number of unsuccessful guesses before a question is considered as failed
*
* @param guessNumber The number of unsuccessful guesses
*/
void setGuessesNumber(final int guessNumber);
/**
* Returns the saved question rates
*
* @return The question rates
*/
Map<QuestionType, Double> questionRates();
/**
* Sets the question rates
*
* @param questionRates The question rates
*/
void setQuestionRates(final Map<QuestionType, Double> questionRates);
/**
* 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
*/
void setBirdPracticeParameters(final Collection<? extends BirdPracticeParameters> birdPracticeParameters);
/**
* Sets the bird practice parameters for a specific bird
*
* @param birdPracticeParameters The parameters
*/
void setBirdPracticeParameters(final BirdPracticeParameters birdPracticeParameters);
}
@@ -1,7 +1,5 @@
package ch.gtache.fro.practice; package ch.gtache.fro.practice;
import ch.gtache.fro.Bird;
import java.util.Map; import java.util.Map;
/** /**
@@ -10,11 +8,11 @@ import java.util.Map;
public interface PracticeParameters { public interface PracticeParameters {
/** /**
* Returns the mapping of bird to bird parameters * Returns the bird parameters
* *
* @return The mapping of bird to bird parameters * @return The parameters
*/ */
Map<Bird, BirdPracticeParameters> birdParameters(); GroupedBirdPracticeParameters birdParameters();
/** /**
* Returns the number of unsuccessful guesses before a question is considered as failed * Returns the number of unsuccessful guesses before a question is considered as failed
@@ -0,0 +1,15 @@
package ch.gtache.fro.practice;
/**
* Represents a profile for a practice session
*/
@FunctionalInterface
public interface PracticeProfile {
/**
* Returns the name of the profile
*
* @return The name
*/
String name();
}
@@ -0,0 +1,9 @@
package ch.gtache.fro.practice;
import ch.gtache.fro.Provider;
/**
* {@link Provider} of {@link PracticeProfile}
*/
public interface PracticeProfileProvider extends Provider<String, PracticeProfile> {
}
@@ -27,7 +27,7 @@ public class ChantOiseauxFrFetcher extends AbstractSeleniumFetcher {
@Override @Override
protected void waitFor() throws IOException { protected void waitFor() throws IOException {
throw new UnsupportedOperationException();
} }
@Override @Override
@@ -37,6 +37,6 @@ public class ChantOiseauxFrFetcher extends AbstractSeleniumFetcher {
@Override @Override
protected void download(final Bird bird) throws FetchException { protected void download(final Bird bird) throws FetchException {
throw new UnsupportedOperationException();
} }
} }
-9
View File
@@ -11,10 +11,6 @@
<artifactId>fro-core</artifactId> <artifactId>fro-core</artifactId>
<properties>
<jackson.version>2.20.0</jackson.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>ch.gtache.fro</groupId> <groupId>ch.gtache.fro</groupId>
@@ -24,11 +20,6 @@
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId> <artifactId>log4j-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.dagger</groupId> <groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId> <artifactId>dagger</artifactId>
@@ -0,0 +1,36 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.Translated;
import java.util.Locale;
import java.util.Map;
import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link BirdFamily}
*
* @param name The family name
* @param translations The translations
*/
public record BirdFamilyImpl(String name, Map<Locale, String> translations) implements BirdFamily, Translated {
/**
* Instantiates the bird family
*
* @param name The family name
* @param translations The translations
* @throws NullPointerException If any parameter is null
*/
public BirdFamilyImpl {
requireNonNull(name);
translations = Map.copyOf(translations);
}
@Override
public String translate(final Locale locale) {
final var translation = Translated.super.translate(locale);
return translation == null ? name : translation;
}
}
@@ -0,0 +1,27 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.BirdFamilyTranslator;
import ch.gtache.fro.Translated;
import jakarta.inject.Inject;
import java.util.Locale;
/**
* Implementation of {@link BirdFamilyTranslator}
*/
public class BirdFamilyTranslatorImpl implements BirdFamilyTranslator {
@Inject
BirdFamilyTranslatorImpl() {
}
@Override
public String translate(final BirdFamily object, final Locale locale) {
if (object instanceof final Translated t) {
return t.translate(locale);
} else {
return object.name();
}
}
}
@@ -1,23 +1,45 @@
package ch.gtache.fro.impl; package ch.gtache.fro.impl;
import ch.gtache.fro.Bird; import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.MigrationType;
import ch.gtache.fro.Translated;
import java.util.Objects; import java.util.Locale;
import java.util.Map;
import static java.util.Objects.requireNonNull;
/** /**
* Implementation of {@link Bird} * Implementation of {@link Bird}
* *
* @param name The bird name * @param name The bird name
* @param family The bird family
* @param migrationType The bird migration type
* @param translations The translations
*/ */
public record BirdImpl(String name) implements Bird { public record BirdImpl(String name, BirdFamily family, MigrationType migrationType,
Map<Locale, String> translations) implements Bird, Translated {
/** /**
* Instantiates the bird * Instantiates the bird
* *
* @param name The bird name * @param name The bird name
* @param family The bird family
* @param migrationType The bird migration type
* @param translations The translations
* @throws NullPointerException If any parameter is null * @throws NullPointerException If any parameter is null
*/ */
public BirdImpl { public BirdImpl {
Objects.requireNonNull(name); requireNonNull(name);
requireNonNull(family);
requireNonNull(migrationType);
translations = Map.copyOf(translations);
}
@Override
public String translate(final Locale locale) {
final var translation = Translated.super.translate(locale);
return translation == null ? name : translation;
} }
} }
@@ -0,0 +1,27 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdTranslator;
import ch.gtache.fro.Translated;
import jakarta.inject.Inject;
import java.util.Locale;
/**
* Implementation of {@link BirdTranslator}
*/
public class BirdTranslatorImpl implements BirdTranslator {
@Inject
BirdTranslatorImpl() {
}
@Override
public String translate(final Bird object, final Locale locale) {
if (object instanceof final Translated t) {
return t.translate(locale);
} else {
return object.name();
}
}
}
@@ -1,6 +1,8 @@
package ch.gtache.fro.impl; package ch.gtache.fro.impl;
import ch.gtache.fro.Bird; import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.MigrationType;
/** /**
* Represents all the birds (on Vogelwarte) * Represents all the birds (on Vogelwarte)
@@ -434,4 +436,15 @@ public enum CommonBirds implements Bird {
VAUTOUR_PERCNOPTERE, VAUTOUR_PERCNOPTERE,
VENTURON_MONTAGNARD, VENTURON_MONTAGNARD,
VERDIER_D_EUROPE, VERDIER_D_EUROPE,
;
@Override
public BirdFamily family() {
throw new UnsupportedOperationException();
}
@Override
public MigrationType migrationType() {
throw new UnsupportedOperationException();
}
} }
@@ -1,32 +0,0 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdTranslator;
import jakarta.inject.Inject;
import java.util.Locale;
/**
* Implementation of {@link BirdTranslator} for {@link CommonBirds}
*/
public class CommonBirdsTranslatorImpl extends AbstractBundleTranslator<Bird> implements BirdTranslator {
@Inject
CommonBirdsTranslatorImpl() {
super("ch.gtache.fro.impl.BirdBundle");
}
@Override
public String translate(final Bird object, final Locale locale) {
if (object instanceof CommonBirds) {
return super.translate(object, locale);
} else {
return object.name();
}
}
@Override
protected String getKey(final Bird object) {
return "bird." + object.name() + ".label";
}
}
@@ -0,0 +1,31 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.PracticeProfile;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
/**
* Implementation of {@link GroupedBirdPracticeParameters}
*
* @param profile The profile
* @param parameters The parameters
*/
public record GroupedBirdPracticeParametersImpl(PracticeProfile profile,
Collection<BirdPracticeParameters> parameters) implements GroupedBirdPracticeParameters {
/**
* Instantiates the parameters
*
* @param profile The profile
* @param parameters The parameters
* @throws NullPointerException If any parameter is null
*/
public GroupedBirdPracticeParametersImpl {
Objects.requireNonNull(profile);
parameters = List.copyOf(parameters);
}
}
@@ -0,0 +1,36 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.MigrationType;
import ch.gtache.fro.Translated;
import java.util.Locale;
import java.util.Map;
import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link MigrationType}
*
* @param name The type name
* @param translations The translations
*/
public record MigrationTypeImpl(String name, Map<Locale, String> translations) implements MigrationType, Translated {
/**
* Instantiates the type
*
* @param name The type name
* @param translations The translations
* @throws NullPointerException If any parameter is null
*/
public MigrationTypeImpl {
requireNonNull(name);
translations = Map.copyOf(translations);
}
@Override
public String translate(final Locale locale) {
final var translation = Translated.super.translate(locale);
return translation == null ? name : translation;
}
}
@@ -0,0 +1,27 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.MigrationType;
import ch.gtache.fro.MigrationTypeTranslator;
import ch.gtache.fro.Translated;
import jakarta.inject.Inject;
import java.util.Locale;
/**
* Implementation of {@link MigrationTypeTranslator}
*/
public class MigrationTypeTranslatorImpl implements MigrationTypeTranslator {
@Inject
MigrationTypeTranslatorImpl() {
}
@Override
public String translate(final MigrationType object, final Locale locale) {
if (object instanceof final Translated t) {
return t.translate(locale);
} else {
return object.name();
}
}
}
@@ -0,0 +1,35 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.MigrationType;
import static java.util.Objects.requireNonNull;
/**
* Minimal implementation of {@link Bird}
*
* @param name The bird name
*/
public record MinimalBirdImpl(String name) implements Bird {
/**
* Instantiates the bird
*
* @param name The bird name
* @throws NullPointerException If any parameter is null
*/
public MinimalBirdImpl {
requireNonNull(name);
}
@Override
public BirdFamily family() {
throw new UnsupportedOperationException("Not supported");
}
@Override
public MigrationType migrationType() {
throw new UnsupportedOperationException("Not supported");
}
}
@@ -0,0 +1,25 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.Bird;
import ch.gtache.fro.Fetcher;
import ch.gtache.fro.FilledBird;
import java.util.List;
/**
* {@link Fetcher} that does nothing
*
* @param name The name of the fetcher
*/
public record NoFetcherImpl(String name) implements Fetcher {
@Override
public List<FilledBird> fetchAll() {
return List.of();
}
@Override
public FilledBird fetch(final Bird bird) {
return new FilledBirdImpl(bird, List.of(), List.of());
}
}
@@ -1,213 +0,0 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdProvider;
import ch.gtache.fro.Fetcher;
import ch.gtache.fro.FetcherProvider;
import ch.gtache.fro.PictureType;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.SoundType;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.PracticeConfiguration;
import ch.gtache.fro.practice.QuestionType;
import ch.gtache.fro.practice.impl.BirdPracticeParametersImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.inject.Inject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link PracticeConfiguration}
*/
public class PracticeConfigurationImpl implements PracticeConfiguration {
private static final Logger logger = LogManager.getLogger(PracticeConfigurationImpl.class);
private static final int DEFAULT_GUESS_NUMBER = 1;
private static final String QUESTION_RATES_KEY = "questionRates";
private static final String BIRD_PRACTICE_PARAMETERS_KEY = "birdPracticeParameters";
private static final String GUESSES_NUMBER_KEY = "guessNumber";
private final BirdProvider birdProvider;
private final FetcherProvider fetcherProvider;
private final ObjectMapper objectMapper;
private final Preferences preferences;
private final Map<Bird, BirdPracticeParameters> birdPracticeParameters;
private final Map<QuestionType, Double> questionRates;
private int guessesNumber;
@Inject
PracticeConfigurationImpl(final BirdProvider birdProvider, final FetcherProvider fetcherProvider, final ObjectMapper objectMapper) {
this.birdProvider = requireNonNull(birdProvider);
this.fetcherProvider = requireNonNull(fetcherProvider);
this.objectMapper = requireNonNull(objectMapper);
this.preferences = Preferences.userNodeForPackage(this.getClass());
this.birdPracticeParameters = new HashMap<>();
this.questionRates = new EnumMap<>(QuestionType.class);
this.guessesNumber = DEFAULT_GUESS_NUMBER;
load();
}
private void load() {
loadBirdPracticeParameters();
loadQuestionRates();
this.guessesNumber = preferences.getInt(GUESSES_NUMBER_KEY, DEFAULT_GUESS_NUMBER);
}
private void loadQuestionRates() {
final var json = preferences.get(QUESTION_RATES_KEY, "{}");
try {
final var deserializedQuestionRates = objectMapper.readValue(json, new QuestionRatesMapTypeReference());
questionRates.putAll(deserializedQuestionRates);
} catch (final JsonProcessingException e) {
logger.error("Failed to deserialize question rates", e);
}
Arrays.stream(QuestionType.values()).forEach(qt -> {
if (!questionRates.containsKey(qt)) {
questionRates.put(qt, qt == QuestionType.PICTURE_EXACT ? 1.0 : 0.0);
}
});
}
private void loadBirdPracticeParameters() {
final var practiceParameters = preferences.get(BIRD_PRACTICE_PARAMETERS_KEY, "[]");
try {
final var deserializedPracticeParameters = deserializeBirdPracticeParameters(objectMapper.readValue(practiceParameters, new SerializedBirdPracticeParametersTypeReference()));
birdPracticeParameters.putAll(deserializedPracticeParameters);
} catch (final JsonProcessingException e) {
logger.error("Failed to deserialize bird parameters", e);
}
try {
final var allBirds = birdProvider.getAllObjects();
allBirds.forEach(b -> {
if (!birdPracticeParameters.containsKey(b)) {
birdPracticeParameters.put(b, getDefaultParameters(b));
}
});
} catch (final ProvisionException e) {
logger.error("Failed to get all birds", e);
}
}
private Map<Bird, BirdPracticeParameters> deserializeBirdPracticeParameters(final List<SerializedBirdPracticeParameters> parameters) {
return parameters.stream().collect(Collectors.toMap(p -> {
try {
return birdProvider.getObject(p.bird());
} catch (final ProvisionException e) {
logger.error("Failed to get bird {}", p.bird(), e);
return null;
}
}, this::deserializeBirdPracticeParameters));
}
private BirdPracticeParameters deserializeBirdPracticeParameters(final SerializedBirdPracticeParameters parameters) {
try {
final var bird = birdProvider.getObject(parameters.bird());
return new BirdPracticeParametersImpl(bird, parameters.enabled(), parameters.enabledFetchers(), parameters.enabledPictureTypes(), parameters.enabledSoundTypes());
} catch (final ProvisionException e) {
logger.error("Failed to get bird {}", parameters.bird(), e);
return null;
}
}
private List<SerializedBirdPracticeParameters> serializeBirdPracticeParameters() {
return birdPracticeParameters.values().stream().map(PracticeConfigurationImpl::serializeBirdPracticeParameters).toList();
}
private static SerializedBirdPracticeParameters serializeBirdPracticeParameters(final BirdPracticeParameters parameters) {
return new SerializedBirdPracticeParameters(parameters.bird().name(), parameters.enabled(), parameters.enabledFetchers(), parameters.enabledPictureTypes(), parameters.enabledSoundTypes());
}
@Override
public int guessesNumber() {
return guessesNumber;
}
@Override
public void setGuessesNumber(final int guessNumber) {
this.guessesNumber = guessNumber;
preferences.putInt(GUESSES_NUMBER_KEY, guessNumber);
}
@Override
public Map<QuestionType, Double> questionRates() {
return new EnumMap<>(questionRates);
}
@Override
public void setQuestionRates(final Map<QuestionType, Double> questionRates) {
this.questionRates.clear();
this.questionRates.putAll(questionRates);
saveQuestionRates();
}
private void saveQuestionRates() {
final String json;
try {
json = objectMapper.writeValueAsString(questionRates);
preferences.put(QUESTION_RATES_KEY, json);
} catch (final JsonProcessingException e) {
logger.error("Failed to serialize question rates", e);
}
}
@Override
public Collection<BirdPracticeParameters> birdPracticeParameters() {
return birdPracticeParameters.values();
}
@Override
public BirdPracticeParameters birdPracticeParameters(final Bird bird) {
return birdPracticeParameters.get(bird);
}
@Override
public void setBirdPracticeParameters(final Collection<? extends BirdPracticeParameters> birdPracticeParameters) {
this.birdPracticeParameters.clear();
this.birdPracticeParameters.putAll(birdPracticeParameters.stream().collect(Collectors.toMap(BirdPracticeParameters::bird, Function.identity())));
saveBirdPracticeParameters();
}
@Override
public void setBirdPracticeParameters(final BirdPracticeParameters birdPracticeParameters) {
this.birdPracticeParameters.put(birdPracticeParameters.bird(), birdPracticeParameters);
saveBirdPracticeParameters();
}
private void saveBirdPracticeParameters() {
final var parameters = serializeBirdPracticeParameters();
try {
final var json = objectMapper.writeValueAsString(parameters);
preferences.put(BIRD_PRACTICE_PARAMETERS_KEY, json);
} catch (final JsonProcessingException e) {
logger.error("Failed to serialize bird parameters", e);
}
}
private BirdPracticeParameters getDefaultParameters(final Bird bird) {
final var pictureTypes = Set.copyOf(Arrays.asList(PictureType.values()));
final var soundTypes = Set.copyOf(Arrays.asList(SoundType.values()));
try {
final var fetcherNames = fetcherProvider.getAllObjects().stream().map(Fetcher::name).collect(Collectors.toSet());
return new BirdPracticeParametersImpl(bird, true, fetcherNames, pictureTypes, soundTypes);
} catch (final ProvisionException e) {
logger.error("Failed to get fetcher names", e);
return new BirdPracticeParametersImpl(bird, true, Set.of(), pictureTypes, soundTypes);
}
}
}
@@ -1,9 +0,0 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.practice.QuestionType;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.Map;
class QuestionRatesMapTypeReference extends TypeReference<Map<QuestionType, Double>> {
}
@@ -1,15 +0,0 @@
package ch.gtache.fro.impl;
import ch.gtache.fro.PictureType;
import ch.gtache.fro.SoundType;
import java.util.Set;
record SerializedBirdPracticeParameters(String bird, boolean enabled, Set<String> enabledFetchers,
Set<PictureType> enabledPictureTypes,
Set<SoundType> enabledSoundTypes) {
SerializedBirdPracticeParameters(final String bird) {
this(bird, false, Set.of(), Set.of(), Set.of());
}
}
@@ -1,8 +0,0 @@
package ch.gtache.fro.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.List;
class SerializedBirdPracticeParametersTypeReference extends TypeReference<List<SerializedBirdPracticeParameters>> {
}
@@ -1,22 +1,26 @@
package ch.gtache.fro.modules.impl; package ch.gtache.fro.modules.impl;
import ch.gtache.fro.BirdProvider; import ch.gtache.fro.BirdFamilyTranslator;
import ch.gtache.fro.BirdTranslator; import ch.gtache.fro.BirdTranslator;
import ch.gtache.fro.Fetcher;
import ch.gtache.fro.FetcherProvider; import ch.gtache.fro.FetcherProvider;
import ch.gtache.fro.MigrationTypeTranslator;
import ch.gtache.fro.PictureTypeTranslator; import ch.gtache.fro.PictureTypeTranslator;
import ch.gtache.fro.SoundTypeTranslator; import ch.gtache.fro.SoundTypeTranslator;
import ch.gtache.fro.impl.CommonBirdsProvider; import ch.gtache.fro.impl.BirdFamilyTranslatorImpl;
import ch.gtache.fro.impl.CommonBirdsTranslatorImpl; import ch.gtache.fro.impl.BirdTranslatorImpl;
import ch.gtache.fro.impl.FetcherProviderImpl; import ch.gtache.fro.impl.FetcherProviderImpl;
import ch.gtache.fro.impl.GroupedBirdPracticeParametersImpl;
import ch.gtache.fro.impl.MigrationTypeTranslatorImpl;
import ch.gtache.fro.impl.NoFetcherImpl;
import ch.gtache.fro.impl.PictureTypeTranslatorImpl; import ch.gtache.fro.impl.PictureTypeTranslatorImpl;
import ch.gtache.fro.impl.PracticeConfigurationImpl;
import ch.gtache.fro.impl.SoundTypeTranslatorImpl; import ch.gtache.fro.impl.SoundTypeTranslatorImpl;
import ch.gtache.fro.modules.practice.impl.CorePracticeModule; import ch.gtache.fro.modules.practice.impl.CorePracticeModule;
import ch.gtache.fro.practice.PracticeConfiguration; import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import dagger.Binds; import dagger.Binds;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import dagger.multibindings.IntoSet;
/** /**
* Dagger module for the core package * Dagger module for the core package
@@ -29,16 +33,19 @@ public abstract class CoreModule {
} }
@Binds @Binds
abstract BirdProvider bindsBirdProvider(final CommonBirdsProvider commonBirdsProvider); abstract GroupedBirdPracticeParameters bindsConfiguration(final GroupedBirdPracticeParametersImpl configurationImpl);
@Binds
abstract PracticeConfiguration bindsConfiguration(final PracticeConfigurationImpl configurationImpl);
@Binds @Binds
abstract FetcherProvider bindsFetcherProvider(final FetcherProviderImpl fetcherProviderImpl); abstract FetcherProvider bindsFetcherProvider(final FetcherProviderImpl fetcherProviderImpl);
@Binds @Binds
abstract BirdTranslator bindsBirdTranslator(final CommonBirdsTranslatorImpl commonBirdsTranslatorImpl); abstract BirdTranslator bindsBirdTranslator(final BirdTranslatorImpl birdTranslatorImpl);
@Binds
abstract BirdFamilyTranslator bindsBirdFamilyTranslator(final BirdFamilyTranslatorImpl birdFamilyTranslatorImpl);
@Binds
abstract MigrationTypeTranslator bindsMigrationTypeTranslator(final MigrationTypeTranslatorImpl migrationTypeTranslatorImpl);
@Binds @Binds
abstract PictureTypeTranslator bindsPictureTypeTranslator(final PictureTypeTranslatorImpl pictureTypeTranslatorImpl); abstract PictureTypeTranslator bindsPictureTypeTranslator(final PictureTypeTranslatorImpl pictureTypeTranslatorImpl);
@@ -47,7 +54,8 @@ public abstract class CoreModule {
abstract SoundTypeTranslator bindsSoundTypeTranslator(final SoundTypeTranslatorImpl soundTypeTranslatorImpl); abstract SoundTypeTranslator bindsSoundTypeTranslator(final SoundTypeTranslatorImpl soundTypeTranslatorImpl);
@Provides @Provides
static ObjectMapper providesObjectMapper() { @IntoSet
return new ObjectMapper(); static Fetcher providesChantOiseauxFetcher() {
return new NoFetcherImpl("chant-oiseaux.fr");
} }
} }
@@ -1,13 +1,11 @@
package ch.gtache.fro.practice.impl; package ch.gtache.fro.practice.impl;
import ch.gtache.fro.Bird; import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.PracticeParameters; import ch.gtache.fro.practice.PracticeParameters;
import ch.gtache.fro.practice.QuestionType; import ch.gtache.fro.practice.QuestionType;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Objects;
/** /**
* Implementation of {@link PracticeParameters} * Implementation of {@link PracticeParameters}
@@ -18,7 +16,7 @@ import java.util.stream.Collectors;
* @param questionsNumber The number of questions * @param questionsNumber The number of questions
* @param propositionsNumber The number of propositions * @param propositionsNumber The number of propositions
*/ */
public record PracticeParametersImpl(Map<Bird, BirdPracticeParameters> birdParameters, public record PracticeParametersImpl(GroupedBirdPracticeParameters birdParameters,
Map<QuestionType, Double> questionTypeRates, Map<QuestionType, Double> questionTypeRates,
int guessesNumber, int questionsNumber, int guessesNumber, int questionsNumber,
int propositionsNumber) implements PracticeParameters { int propositionsNumber) implements PracticeParameters {
@@ -35,7 +33,7 @@ public record PracticeParametersImpl(Map<Bird, BirdPracticeParameters> birdParam
* @throws IllegalArgumentException If questionsCount is less than 1 * @throws IllegalArgumentException If questionsCount is less than 1
*/ */
public PracticeParametersImpl { public PracticeParametersImpl {
birdParameters = Map.copyOf(birdParameters); Objects.requireNonNull(birdParameters);
questionTypeRates = Map.copyOf(questionTypeRates); questionTypeRates = Map.copyOf(questionTypeRates);
if (guessesNumber <= 0) { if (guessesNumber <= 0) {
throw new IllegalArgumentException("guessesNumber must be > 0"); throw new IllegalArgumentException("guessesNumber must be > 0");
@@ -44,22 +42,4 @@ public record PracticeParametersImpl(Map<Bird, BirdPracticeParameters> birdParam
throw new IllegalArgumentException("questionsCount must be > 0"); throw new IllegalArgumentException("questionsCount must be > 0");
} }
} }
/**
* Instantiates the parameters
*
* @param birdParameters The bird parameters
* @param questionTypeRates The practice type rates
* @param guessesNumber The number of unsuccessful guesses before a question is considered as failed
* @param questionsNumber The number of questions
* @param propositionsNumber The number of propositions
* @throws NullPointerException If any parameter is null
* @throws IllegalArgumentException If questionsCount is less than 1
*/
public PracticeParametersImpl(final Collection<? extends BirdPracticeParameters> birdParameters,
final Map<QuestionType, Double> questionTypeRates, final int guessesNumber,
final int questionsNumber, final int propositionsNumber) {
this(birdParameters.stream().collect(Collectors.toMap(BirdPracticeParameters::bird, e -> e)),
questionTypeRates, guessesNumber, questionsNumber, propositionsNumber);
}
} }
@@ -0,0 +1,23 @@
package ch.gtache.fro.practice.impl;
import ch.gtache.fro.practice.PracticeProfile;
import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link PracticeProfile}
*
* @param name The name of the profile
*/
public record PracticeProfileImpl(String name) implements PracticeProfile {
/**
* Instantiates the profile
*
* @param name The name of the profile
* @throws NullPointerException If any parameter is null
*/
public PracticeProfileImpl {
requireNonNull(name);
}
}
@@ -48,7 +48,7 @@ public class PracticeQuestionGeneratorImpl implements PracticeQuestionGenerator
@Override @Override
public PracticeQuestion generate(final PracticeParameters parameters) { public PracticeQuestion generate(final PracticeParameters parameters) {
final var enabledBirds = parameters.birdParameters().values().stream() final var enabledBirds = parameters.birdParameters().parameters().stream()
.filter(p -> p.enabled() && !p.enabledFetchers().isEmpty()).toList(); .filter(p -> p.enabled() && !p.enabledFetchers().isEmpty()).toList();
final var questionType = getQuestionType(parameters.questionTypeRates()); final var questionType = getQuestionType(parameters.questionTypeRates());
return switch (questionType) { return switch (questionType) {
+1 -5
View File
@@ -3,18 +3,14 @@
*/ */
module ch.gtache.fro.core { module ch.gtache.fro.core {
requires transitive ch.gtache.fro.api; requires transitive ch.gtache.fro.api;
requires transitive com.fasterxml.jackson.core;
requires transitive dagger; requires transitive dagger;
requires org.apache.logging.log4j; requires org.apache.logging.log4j;
requires java.prefs;
requires jakarta.inject; requires jakarta.inject;
requires com.fasterxml.jackson.databind; requires java.prefs;
exports ch.gtache.fro.impl; exports ch.gtache.fro.impl;
exports ch.gtache.fro.practice.impl; exports ch.gtache.fro.practice.impl;
exports ch.gtache.fro.modules.impl; exports ch.gtache.fro.modules.impl;
exports ch.gtache.fro.modules.practice.impl; exports ch.gtache.fro.modules.practice.impl;
opens ch.gtache.fro.impl to com.fasterxml.jackson.databind;
} }
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>fro-database</artifactId>
<dependencies>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,91 @@
package ch.gtache.fro.database;
import ch.gtache.fro.BirdFamily;
import ch.gtache.fro.BirdFamilyProvider;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.impl.BirdFamilyImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* {@link BirdFamilyProvider} using a database
*/
@Singleton
public class DatabaseBirdFamilyProvider implements BirdFamilyProvider {
private static final String BASE_REQUEST = "SELECT f.name, ft.translation FROM family f JOIN family_translation ft ON f.id=ft.family_id JOIN language l ON ft.language_id=l.id WHERE l.name='FR'";
private final Connection connection;
private final Map<String, BirdFamily> cache;
private final AtomicBoolean retrievedAll;
@Inject
DatabaseBirdFamilyProvider(final Connection connection) {
this.connection = requireNonNull(connection);
this.cache = new ConcurrentHashMap<>();
this.retrievedAll = new AtomicBoolean(false);
}
@Override
public BirdFamily getObject(final String name) throws ProvisionException {
if (cache.containsKey(name)) {
return cache.get(name);
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST + " AND f.name=?")) {
stmt.setString(1, name);
try (final var rs = stmt.executeQuery()) {
if (rs.next()) {
final var family = parse(rs);
cache.put(name, family);
return family;
} else {
return null;
}
}
} catch (final SQLException e) {
throw new ProvisionException("Error while getting object " + name, e);
}
}
}
@Override
public Collection<BirdFamily> getAllObjects() throws ProvisionException {
if (retrievedAll.get()) {
return cache.values();
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST);
final var rs = stmt.executeQuery()) {
final var ret = new ArrayList<BirdFamily>();
while (rs.next()) {
ret.add(parse(rs));
}
cache.putAll(ret.stream().collect(Collectors.toMap(BirdFamily::name, Function.identity())));
retrievedAll.set(true);
return ret;
} catch (final SQLException e) {
throw new ProvisionException("Error while getting all objects", e);
}
}
}
private static BirdFamily parse(final ResultSet rs) throws SQLException {
final var name = rs.getString(1);
final var translation = rs.getString(2);
return new BirdFamilyImpl(name, Map.of(Locale.FRENCH, translation));
}
}
@@ -0,0 +1,103 @@
package ch.gtache.fro.database;
import ch.gtache.fro.Bird;
import ch.gtache.fro.BirdFamilyProvider;
import ch.gtache.fro.BirdProvider;
import ch.gtache.fro.MigrationTypeProvider;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.impl.BirdImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* {@link BirdProvider} using a database
*/
@Singleton
public class DatabaseBirdProvider implements BirdProvider {
private static final String BASE_REQUEST = "SELECT b.name, f.name, m.name, bt.translation FROM bird b JOIN family f ON b.family_id=f.id JOIN migration_type m ON b.migration_type_id=m.id JOIN bird_translation bt ON b.id=bt.bird_id JOIN language l ON bt.language_id=l.id WHERE l.name='FR'";
private final Connection connection;
private final BirdFamilyProvider birdFamilyProvider;
private final MigrationTypeProvider migrationTypeProvider;
private final Map<String, Bird> cache;
private final AtomicBoolean retrievedAll;
@Inject
DatabaseBirdProvider(final Connection connection,
final BirdFamilyProvider birdFamilyProvider,
final MigrationTypeProvider migrationTypeProvider) {
this.connection = requireNonNull(connection);
this.birdFamilyProvider = requireNonNull(birdFamilyProvider);
this.migrationTypeProvider = requireNonNull(migrationTypeProvider);
this.cache = new ConcurrentHashMap<>();
this.retrievedAll = new AtomicBoolean(false);
}
@Override
public Bird getObject(final String name) throws ProvisionException {
if (cache.containsKey(name)) {
return cache.get(name);
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST + " AND b.name=?")) {
stmt.setString(1, name);
try (final var rs = stmt.executeQuery()) {
if (rs.next()) {
final var bird = parse(rs);
cache.put(name, bird);
return bird;
} else {
return null;
}
}
} catch (final SQLException e) {
throw new ProvisionException("Error while getting object " + name, e);
}
}
}
@Override
public Collection<Bird> getAllObjects() throws ProvisionException {
if (retrievedAll.get()) {
return cache.values();
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST);
final var rs = stmt.executeQuery()) {
final var ret = new ArrayList<Bird>();
while (rs.next()) {
ret.add(parse(rs));
}
cache.putAll(ret.stream().collect(Collectors.toMap(Bird::name, Function.identity())));
retrievedAll.set(true);
return ret;
} catch (final SQLException e) {
throw new ProvisionException("Error while getting all objects", e);
}
}
}
private Bird parse(final ResultSet rs) throws SQLException, ProvisionException {
final var name = rs.getString(1);
final var familyName = rs.getString(2);
final var migrationTypeName = rs.getString(3);
final var translation = rs.getString(4);
final var family = birdFamilyProvider.getObject(familyName);
final var migrationType = migrationTypeProvider.getObject(migrationTypeName);
return new BirdImpl(name, family, migrationType, Map.of(Locale.FRENCH, translation));
}
}
@@ -0,0 +1,58 @@
package ch.gtache.fro.database;
import ch.gtache.fro.Initializer;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
/**
* {@link Initializer} for the database
*/
@Singleton
public class DatabaseInitializer implements Initializer {
private final Connection connection;
@Inject
DatabaseInitializer(final Connection connection) {
this.connection = Objects.requireNonNull(connection);
}
@Override
public void initialize() {
try {
if (!isInitialized()) {
final var files = List.of("init.sql", "init-data.sql", "init-translations.sql", "init-fro1.sql");
final var runner = new ScriptRunner(connection);
for (final var file : files) {
try (final var reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(file), StandardCharsets.UTF_8))) {
runner.runScript(reader);
}
}
}
} catch (final IOException | SQLException e) {
throw new RuntimeException("Error running initialization scripts", e);
}
}
private boolean isInitialized() throws SQLException {
try (final var stmt = connection.prepareStatement("SELECT 1 FROM profile WHERE name='FRO1'");
final var rs = stmt.executeQuery()) {
return rs.next();
} catch (final SQLException e) {
if (e.getMessage().contains("not found")) {
return false;
} else {
throw e;
}
}
}
}
@@ -0,0 +1,91 @@
package ch.gtache.fro.database;
import ch.gtache.fro.MigrationType;
import ch.gtache.fro.MigrationTypeProvider;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.impl.MigrationTypeImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* {@link MigrationTypeProvider} using a database
*/
@Singleton
public class DatabaseMigrationTypeProvider implements MigrationTypeProvider {
private static final String BASE_REQUEST = "SELECT mt.name, mtt.translation FROM migration_type mt JOIN migration_type_translation mtt ON mt.id=mtt.migration_type_id JOIN language l ON mtt.language_id=l.id WHERE l.name='FR'";
private final Connection connection;
private final Map<String, MigrationType> cache;
private final AtomicBoolean retrievedAll;
@Inject
DatabaseMigrationTypeProvider(final Connection connection) {
this.connection = requireNonNull(connection);
this.cache = new ConcurrentHashMap<>();
this.retrievedAll = new AtomicBoolean(false);
}
@Override
public MigrationType getObject(final String name) throws ProvisionException {
if (cache.containsKey(name)) {
return cache.get(name);
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST + " AND mt.name=?")) {
stmt.setString(1, name);
try (final var rs = stmt.executeQuery()) {
if (rs.next()) {
final var type = parse(rs);
cache.put(name, type);
return type;
} else {
return null;
}
}
} catch (final SQLException e) {
throw new ProvisionException("Error while getting object " + name, e);
}
}
}
@Override
public Collection<MigrationType> getAllObjects() throws ProvisionException {
if (retrievedAll.get()) {
return cache.values();
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST);
final var rs = stmt.executeQuery()) {
final var ret = new ArrayList<MigrationType>();
while (rs.next()) {
ret.add(parse(rs));
}
cache.putAll(ret.stream().collect(Collectors.toMap(MigrationType::name, Function.identity())));
retrievedAll.set(true);
return ret;
} catch (final SQLException e) {
throw new ProvisionException("Error while getting all objects", e);
}
}
}
private static MigrationType parse(final ResultSet rs) throws SQLException {
final var name = rs.getString(1);
final var translation = rs.getString(2);
return new MigrationTypeImpl(name, Map.of(Locale.FRENCH, translation));
}
}
@@ -0,0 +1,71 @@
package ch.gtache.fro.database;
/*
* Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class
* from the iBATIS Apache project. Only removed dependency on Resource class
* and a constructor
*/
/*
* Copyright 2004 Clinton Begin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Tool to run database scripts
*/
public class ScriptRunner {
private static final String DELIMITER = ";";
private final Connection connection;
/**
* Default constructor
*/
public ScriptRunner(final Connection connection) {
this.connection = connection;
}
/**
* Runs an SQL script (read in using the Reader parameter)
*
* @param reader - the source of the script
*/
public void runScript(final Reader reader) throws IOException, SQLException {
final var lineReader = new LineNumberReader(reader);
String line;
final var command = new StringBuilder();
while ((line = lineReader.readLine()) != null) {
final var trimmedLine = line.trim();
if (!trimmedLine.startsWith("--") && !trimmedLine.isEmpty() && !trimmedLine.startsWith("//")) {
if (trimmedLine.endsWith(DELIMITER)) {
command.append(line, 0, line.lastIndexOf(DELIMITER));
command.append(" ");
try (final var statement = connection.createStatement()) {
statement.execute(command.toString());
}
command.setLength(0);
} else {
command.append(line);
command.append(" ");
}
}
}
}
}
@@ -0,0 +1,38 @@
package ch.gtache.fro.modules.database;
import ch.gtache.fro.BirdFamilyProvider;
import ch.gtache.fro.BirdProvider;
import ch.gtache.fro.Initializer;
import ch.gtache.fro.MigrationTypeProvider;
import ch.gtache.fro.database.DatabaseBirdFamilyProvider;
import ch.gtache.fro.database.DatabaseBirdProvider;
import ch.gtache.fro.database.DatabaseInitializer;
import ch.gtache.fro.database.DatabaseMigrationTypeProvider;
import ch.gtache.fro.modules.practice.database.DatabasePracticeModule;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoSet;
/**
* Dagger module for database
*/
@Module(includes = DatabasePracticeModule.class)
public abstract class DatabaseModule {
private DatabaseModule() {
}
@Binds
abstract BirdProvider bindsBirdProvider(DatabaseBirdProvider databaseBirdProvider);
@Binds
abstract BirdFamilyProvider bindsBirdFamilyProvider(DatabaseBirdFamilyProvider databaseBirdFamilyProvider);
@Binds
abstract MigrationTypeProvider bindsMigrationTypeProvider(DatabaseMigrationTypeProvider databaseMigrationTypeProvider);
@Binds
@IntoSet
abstract Initializer bindsInitializer(DatabaseInitializer databaseInitializer);
}
@@ -0,0 +1,25 @@
package ch.gtache.fro.modules.practice.database;
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
import ch.gtache.fro.practice.PracticeProfileProvider;
import ch.gtache.fro.practice.database.DatabaseGroupedBirdPracticeParametersManager;
import ch.gtache.fro.practice.database.DatabasePracticeProfileProvider;
import dagger.Binds;
import dagger.Module;
/**
* Dagger module for database practice
*/
@Module
public abstract class DatabasePracticeModule {
private DatabasePracticeModule() {
}
@Binds
abstract GroupedBirdPracticeParametersManager bindsGroupedBirdPracticeParametersManager(DatabaseGroupedBirdPracticeParametersManager databaseGroupedBirdPracticeParametersManager);
@Binds
abstract PracticeProfileProvider bindsPracticeProfileProvider(DatabasePracticeProfileProvider databasePracticeProfileProvider);
}
@@ -0,0 +1,135 @@
package ch.gtache.fro.practice.database;
import ch.gtache.fro.BirdProvider;
import ch.gtache.fro.PictureType;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.SoundType;
import ch.gtache.fro.impl.GroupedBirdPracticeParametersImpl;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
import ch.gtache.fro.practice.PracticeProfile;
import ch.gtache.fro.practice.PracticeProfileProvider;
import ch.gtache.fro.practice.impl.BirdPracticeParametersImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.Objects.requireNonNull;
/**
* {@link GroupedBirdPracticeParametersManager} using a database
*/
@Singleton
public class DatabaseGroupedBirdPracticeParametersManager implements GroupedBirdPracticeParametersManager {
private static final String BASE_REQUEST = "SELECT p.name, b.name, bp.enabled, " +
"array(SELECT pt.name FROM picture_type pt JOIN bird_parameters_picture_type bppt ON pt.id=bppt.picture_type_id WHERE bppt.bird_parameters_id=bp.id), " +
"array(SELECT st.name FROM sound_type st JOIN bird_parameters_sound_type bpst ON st.id=bpst.sound_type_id WHERE bpst.bird_parameters_id=bp.id), " +
"array(SELECT f.name FROM fetcher f JOIN bird_parameters_fetcher bpf ON f.id=bpf.fetcher_id WHERE bpf.bird_parameters_id=bp.id) FROM profile p JOIN bird_parameters bp ON p.id=bp.profile_id JOIN bird b ON bp.bird_id=b.id";
private final Connection connection;
private final BirdProvider birdProvider;
private final PracticeProfileProvider profileProvider;
private final Map<PracticeProfile, GroupedBirdPracticeParameters> cache;
private final AtomicBoolean retrievedAll;
@Inject
DatabaseGroupedBirdPracticeParametersManager(final Connection connection,
final BirdProvider birdProvider,
final PracticeProfileProvider profileProvider) {
this.connection = requireNonNull(connection);
this.birdProvider = requireNonNull(birdProvider);
this.profileProvider = requireNonNull(profileProvider);
this.cache = new ConcurrentHashMap<>();
this.retrievedAll = new AtomicBoolean(false);
}
@Override
public GroupedBirdPracticeParameters getObject(final PracticeProfile profile) throws ProvisionException {
if (cache.containsKey(profile)) {
return cache.get(profile);
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST + " WHERE p.name=?")) {
stmt.setString(1, profile.name());
try (final var rs = stmt.executeQuery()) {
final var parameters = new ArrayList<BirdPracticeParameters>();
while (rs.next()) {
parameters.add(parse(rs).parameters());
}
final var groupedParameters = new GroupedBirdPracticeParametersImpl(profile, parameters);
cache.put(profile, groupedParameters);
return groupedParameters;
}
} catch (final SQLException e) {
throw new ProvisionException("Error while getting object " + profile, e);
}
}
}
@Override
public Collection<GroupedBirdPracticeParameters> getAllObjects() throws ProvisionException {
if (retrievedAll.get()) {
return cache.values();
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST);
final var rs = stmt.executeQuery()) {
final var parameters = new ArrayList<ParametersPair>();
while (rs.next()) {
parameters.add(parse(rs));
}
final var map = new HashMap<String, Set<BirdPracticeParameters>>();
for (final var parameter : parameters) {
map.computeIfAbsent(parameter.profileName(), k -> new HashSet<>()).add(parameter.parameters());
}
final var ret = new ArrayList<GroupedBirdPracticeParameters>(map.size());
for (final var entry : map.entrySet()) {
final var profile = profileProvider.getObject(entry.getKey());
final var groupedParameters = new GroupedBirdPracticeParametersImpl(profile, entry.getValue());
cache.put(profile, groupedParameters);
ret.add(groupedParameters);
}
retrievedAll.set(true);
return ret;
} catch (final SQLException e) {
throw new ProvisionException("Error while getting all objects", e);
}
}
}
@Override
public void save(final GroupedBirdPracticeParameters configuration, final PracticeProfile profile) {
throw new UnsupportedOperationException("Not implemented");
}
private ParametersPair parse(final ResultSet rs) throws SQLException, ProvisionException {
final var profileName = rs.getString(1);
final var birdName = rs.getString(2);
final var enabled = rs.getBoolean(3);
final var pictureTypesArray = rs.getArray(4);
final var pictureTypes = Arrays.stream((Object[]) pictureTypesArray.getArray()).map(o -> PictureType.valueOf((String) o)).toList();
final var soundTypesArray = rs.getArray(5);
final var soundTypes = Arrays.stream((Object[]) soundTypesArray.getArray()).map(o -> SoundType.valueOf((String) o)).toList();
final var fetchersArray = rs.getArray(6);
final var fetchers = Arrays.stream((Object[]) fetchersArray.getArray()).map(String.class::cast).toList();
final var bird = birdProvider.getObject(birdName);
return new ParametersPair(new BirdPracticeParametersImpl(bird, enabled, Set.copyOf(fetchers), Set.copyOf(pictureTypes), Set.copyOf(soundTypes)), profileName);
}
private record ParametersPair(BirdPracticeParameters parameters, String profileName) {
}
}
@@ -0,0 +1,89 @@
package ch.gtache.fro.practice.database;
import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.practice.PracticeProfile;
import ch.gtache.fro.practice.PracticeProfileProvider;
import ch.gtache.fro.practice.impl.PracticeProfileImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* {@link PracticeProfileProvider} using a database
*/
@Singleton
public class DatabasePracticeProfileProvider implements PracticeProfileProvider {
private static final String BASE_REQUEST = "SELECT p.name FROM profile p";
private final Connection connection;
private final Map<String, PracticeProfile> cache;
private final AtomicBoolean retrievedAll;
@Inject
DatabasePracticeProfileProvider(final Connection connection) {
this.connection = requireNonNull(connection);
this.cache = new ConcurrentHashMap<>();
this.retrievedAll = new AtomicBoolean(false);
}
@Override
public PracticeProfile getObject(final String name) throws ProvisionException {
if (cache.containsKey(name)) {
return cache.get(name);
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST + " WHERE p.name=?")) {
stmt.setString(1, name);
try (final var rs = stmt.executeQuery()) {
if (rs.next()) {
final var profile = parse(rs);
cache.put(name, profile);
return profile;
} else {
return null;
}
}
} catch (final SQLException e) {
throw new ProvisionException("Error while getting object " + name, e);
}
}
}
@Override
public Collection<PracticeProfile> getAllObjects() throws ProvisionException {
if (retrievedAll.get()) {
return cache.values();
} else {
try (final var stmt = connection.prepareStatement(BASE_REQUEST);
final var rs = stmt.executeQuery()) {
final var ret = new ArrayList<PracticeProfile>();
while (rs.next()) {
ret.add(parse(rs));
}
cache.putAll(ret.stream().collect(Collectors.toMap(PracticeProfile::name, Function.identity())));
retrievedAll.set(true);
return ret;
} catch (final SQLException e) {
throw new ProvisionException("Error while getting all objects", e);
}
}
}
private static PracticeProfile parse(final ResultSet rs) throws SQLException {
final var name = rs.getString(1);
return new PracticeProfileImpl(name);
}
}
+14
View File
@@ -0,0 +1,14 @@
/**
* Database module for the FRO application
*/
module ch.gtache.fro.database {
requires transitive ch.gtache.fro.core;
requires transitive jakarta.inject;
requires transitive java.sql;
requires ch.gtache.fro.api;
exports ch.gtache.fro.database;
exports ch.gtache.fro.practice.database;
exports ch.gtache.fro.modules.database;
exports ch.gtache.fro.modules.practice.database;
}
@@ -0,0 +1,957 @@
INSERT INTO family(name)
VALUES ('ANATIDES'),
('PHASIANIDES'),
('PODICIPEDIDES'),
('CICONIIDES'),
('ARDEIDES'),
('PHALACROCORACIDES'),
('ACCIPITRIDES'),
('RALLIDES'),
('CHARADRIIDES'),
('SCOLOPACIDES'),
('LARIDES'),
('COLUMBIDES'),
('CUCULIDES'),
('TYTONIDES'),
('STRIGIDES'),
('CAPRIMULGIDES'),
('APODIDES'),
('ALCEDINIDES'),
('MEROPIDES'),
('UPUPIDES'),
('PICIDES'),
('FALCONIDES'),
('LANIIDES'),
('ORIOLIDES'),
('CORVIDES'),
('PARIDES'),
('PANURIDES'),
('ALAUDIDES'),
('HIRUNDINIDES'),
('AEGITHALIDES'),
('PHYLLOSCOPIDES'),
('ACROCEPHALIDES'),
('LOCUSTELLIDES'),
('SYLVIDES'),
('REGULIDES'),
('TROGLODYTIDES'),
('SITTIDES'),
('TICHODROMIDES'),
('CERTHIIDES'),
('STURNIDES'),
('TURDIDES'),
('MUSCICAPIDES'),
('CINCLIDES'),
('PASSERIDES'),
('PRUNELLIDES'),
('MOTACILLIDES'),
('FRINGILLIDES'),
('EMBERIZIDES'),
('UNKNOWN');
INSERT INTO migration_type(name)
VALUES ('MIGRATION_COURTE_PARTIELLE'),
('MIGRATION_LONGUE_PARTIELLE'),
('MIGRATION_COURTE'),
('MIGRATION_LONGUE'),
('SEDENTAIRE'),
('UNKNOWN');
INSERT INTO bird (family_id, migration_type_id, name)
VALUES ((SELECT id FROM family WHERE name = 'PRUNELLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ACCENTEUR_ALPIN'),
((SELECT id FROM family WHERE name = 'PRUNELLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ACCENTEUR_MOUCHET'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AGROBATE_ROUX'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AIGLE_BOTTE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AIGLE_CRIARD'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AIGLE_POMARIN'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AIGLE_ROYAL'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AIGRETTE_GARZETTE'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_CALANDRE'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_CALANDRELLE'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_DES_CHAMPS'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_HAUSSECOL'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_LEUCOPTERE'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_LULU'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_MONTICOLE'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ALOUETTE_PISPOLETTE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AUTOUR_DES_PALOMBES'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'AVOCETTE_ELEGANTE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BALBUZARD_PECHEUR'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BARGE_A_QUEUE_NOIRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BARGE_ROUSSE'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BEC_CROISE_DES_SAPINS'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSE_DES_BOIS'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_COCORLI'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_DE_BONAPARTE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_DE_TEMMINCK'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_FALCINELLE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_MAUBECHE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_MINUTE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_ROUSSET'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_SANDERLING'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_TACHETE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_VARIABLE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSEAU_VIOLET'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSINE_DES_MARAIS'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSINE_DOUBLE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BECASSINE_SOURDE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERGERONNETTE_CITRINE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERGERONNETTE_DES_RUISSEAUX'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERGERONNETTE_GRISE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERGERONNETTE_PRINTANIERE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERNACHE_A_COU_ROUX'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERNACHE_CRAVANT'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERNACHE_DU_CANADA'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BERNACHE_NONNETTE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BIHOREAU_GRIS'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BLONGIOS_NAIN'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BONDREE_APIVORE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BOUSCARLE_DE_CETTI'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BOUVREUIL_PIVOINE'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_A_CALOTTE_BLANCHE'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_CHANTEUR'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_DES_NEIGES'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_DES_ROSEAUX'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_FOU'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_JAUNE'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_LAPON'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_MELANOCEPHALE'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_NAIN'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_ORTOLAN'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_PROYER'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_RUSTIQUE'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BRUANT_ZIZI'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSARD_CENDRE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSARD_DES_ROSEAUX'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSARD_PALE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSARD_SAINT_MARTIN'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSE_FEROCE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSE_PATTUE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUSE_VARIABLE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'BUTOR_ETOILE'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CAILLE_DES_BLES'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_CAROLIN'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_CHIPEAU'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_COLVERT'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_MANDARIN'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_PILET'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_SIFFLEUR'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CANARD_SOUCHET'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CASSENOIX_MOUCHETE'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHARDONNERET_ELEGANT'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_ABOYEUR'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_ARLEQUIN'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_BARGETTE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_CULBLANC'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_GAMBETTE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_GRIVELE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_GUIGNETTE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_STAGNATILE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVALIER_SYLVAIN'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVECHE_D_ATHENA'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHEVECHETTE_D_EUROPE'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHOCARD_A_BEC_JAUNE'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHOUCAS_DES_TOURS'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHOUETTE_DE_TENGMALM'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHOUETTE_EPERVIERE'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CHOUETTE_HULOTTE'),
((SELECT id FROM family WHERE name = 'CICONIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CIGOGNE_BLANCHE'),
((SELECT id FROM family WHERE name = 'CICONIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CIGOGNE_NOIRE'),
((SELECT id FROM family WHERE name = 'CINCLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CINCLE_PLONGEUR'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CIRCAETE_JEAN_LE_BLANC'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CISTICOLE_DES_JONCS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COCHEVIS_HUPPE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COMBATTANT_VARIE'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CORBEAU_FREUX'),
((SELECT id FROM family WHERE name = 'PHALACROCORACIDES'),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'CORMORAN_HUPPE'),
((SELECT id FROM family WHERE name = 'PHALACROCORACIDES'),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'CORMORAN_PYGMEE'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CORNEILLE_MANTELEE'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CORNEILLE_NOIRE'),
((SELECT id FROM family WHERE name = 'CUCULIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COUCOU_GEAI'),
((SELECT id FROM family WHERE name = 'CUCULIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COUCOU_GRIS'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COURLIS_A_BEC_GRELE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COURLIS_CENDRE'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COURLIS_CORLIEU'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'COURVITE_ISABELLE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CRABIER_CHEVELU'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CRAVE_A_BEC_ROUGE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CYGNE_CHANTEUR'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CYGNE_DE_BEWICK'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'CYGNE_TUBERCULE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'DURBEC_DES_SAPINS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ECHASSE_BLANCHE'),
((SELECT id FROM family WHERE name = 'TYTONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'EFFRAIE_DES_CLOCHERS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'EIDER_A_DUVET'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ELANION_BLANC'),
((SELECT id FROM family WHERE name = 'CAPRIMULGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ENGOULEVENT_D_EUROPE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'EPERVIER_D_EUROPE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ERISMATURE_A_TETE_BLANCHE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ERISMATURE_ROUSSE'),
((SELECT id FROM family WHERE name = 'STURNIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ETOURNEAU_ROSELIN'),
((SELECT id FROM family WHERE name = 'STURNIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ETOURNEAU_SANSONNET'),
((SELECT id FROM family WHERE name = 'STURNIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ETOURNEAU_UNICOLORE'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAISAN_DE_COLCHIDE'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_CRECERELLE'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_CRECERELLETTE'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_D_ELEONORE'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_EMERILLON'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_GERFAUT'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_HOBEREAU'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_KOBEZ'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_PELERIN'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUCON_SACRE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_A_LUNETTES'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_A_TETE_NOIRE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_BABILLARDE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_DES_JARDINS'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_EPERVIERE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_GRISETTE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_MELANOCEPHALE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_ORPHEE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_PASSERINETTE'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FAUVETTE_PITCHOU'),
((SELECT id FROM family WHERE name = 'UNKNOWN' /* ou CICONIIDES selon classification */),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'FLAMANT_ROSE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FOU_DE_BASSAN'),
((SELECT id FROM family WHERE name = 'RALLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FOULQUE_MACROULE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_A_BEC_CERCLE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_A_TETE_NOIRE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_MILOUIN'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_MILOUINAN'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_MORILLON'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'FULIGULE_NYROCA'),
((SELECT id FROM family WHERE name = 'RALLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GALLINULE_POULE_D_EAU'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GARROT_A_OEIL_D_OR'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GEAI_DES_CHENES'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GELINOTTE_DES_BOIS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GLAREOLE_A_AILES_NOIRES'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GLAREOLE_A_COLLIER'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOBEMOUCHE_A_COLLIER'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOBEMOUCHE_A_DEMI_COLLIER'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOBEMOUCHE_GRIS'),
((SELECT id FROM family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOBEMOUCHE_NAIN'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOBEMOUCHE_NOIR'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_A_AILES_BLANCHES'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_ARGENTE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_BOURGMESTRE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_BRUN'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_CENDRE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_D_AUDOUIN'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_LEUCOPHEE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_MARIN'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_PONTIQUE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GOELAND_RAILLEUR'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GORGEBLEUE_A_MIROIR'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAND_CORBEAU'),
((SELECT id FROM family WHERE name = 'PHALACROCORACIDES'),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'GRAND_CORMORAN'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAND_GRAVELOT'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAND_LABBE'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAND_TETRAS'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAND_DUC_D_EUROPE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRANDE_AIGRETTE'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAVELOT_A_COLLIER_INTERROMPU'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRAVELOT_KILDIR'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GREBE_A_COU_NOIR'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GREBE_CASTAGNEUX'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GREBE_ESCLAVON'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GREBE_HUPPE'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GREBE_JOUGRIS'),
((SELECT id FROM family WHERE name = 'CERTHIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIMPEREAU_DES_BOIS'),
((SELECT id FROM family WHERE name = 'CERTHIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIMPEREAU_DES_JARDINS'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIVE_DE_SIBERIE'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIVE_DRAINE'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIVE_LITORNE'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIVE_MAUVIS'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRIVE_MUSICIENNE'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GROSBEC_CASSE_NOYAUX'),
((SELECT id FROM family WHERE name = 'CERTHIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GRUE_CENDREE'),
((SELECT id FROM family WHERE name = 'MEROPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUEPIER_D_EUROPE'),
((SELECT id FROM family WHERE name = 'MEROPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUEPIER_DE_PERSE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUIFETTE_LEUCOPTERE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUIFETTE_MOUSTAC'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUIFETTE_NOIRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUILLEMOT_A_LONG_BEC'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GUILLEMOT_DE_TROIL'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'GYPAETE_BARBU'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HARELDE_BOREALE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HARLE_BIEVRE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HARLE_HUPPE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HARLE_PIETTE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HERON_CENDRE'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HERON_GARDE_BOEUFS'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HERON_POURPRE'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIBOU_DES_MARAIS'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIBOU_MOYEN_DUC'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIRONDELLE_DE_FENETRE'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIRONDELLE_DE_RIVAGE'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIRONDELLE_DE_ROCHERS'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIRONDELLE_ROUSSELINE'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HIRONDELLE_RUSTIQUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HUITRIER_PIE'),
((SELECT id FROM family WHERE name = 'UPUPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HUPPE_FASCIEE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HYPOLAIS_BOTTEE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HYPOLAIS_ICTERINE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'HYPOLAIS_POLYGLOTTE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'IBIS_CHAUVE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'IBIS_FALCINELLE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'IBIS_SACRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'IRANIE_A_GORGE_BLANCHE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'JASEUR_BOREAL'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LABBE_A_LONGUE_QUEUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LABBE_PARASITE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LABBE_POMARIN'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LAGOPEDE_ALPIN'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LINOTTE_A_BEC_JAUNE'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LINOTTE_MELODIEUSE'),
((SELECT id FROM family WHERE name = 'LOCUSTELLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LOCUSTELLE_FLUVIATILE'),
((SELECT id FROM family WHERE name = 'LOCUSTELLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LOCUSTELLE_LUSCINIOIDE'),
((SELECT id FROM family WHERE name = 'LOCUSTELLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LOCUSTELLE_TACHETEE'),
((SELECT id FROM family WHERE name = 'ORIOLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LORIOT_D_EUROPE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'LUSCINIOLE_A_MOUSTACHES'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MACREUSE_BRUNE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MACREUSE_NOIRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MAROUETTE_DE_BAILLON'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MAROUETTE_PONCTUEE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MAROUETTE_POUSSIN'),
((SELECT id FROM family WHERE name = 'ALCEDINIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MARTIN_PECHEUR_D_EUROPE'),
((SELECT id FROM family WHERE name = 'APODIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MARTINET_A_VENTRE_BLANC'),
((SELECT id FROM family WHERE name = 'APODIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MARTINET_NOIR'),
((SELECT id FROM family WHERE name = 'APODIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MARTINET_PALE'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MERLE_A_PLASTRON'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MERLE_NOIR'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_A_LONGUE_QUEUE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_ALPESTRE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_BLEUE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_BOREALE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_CHARBONNIERE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_DES_SAULES'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_HUPPEE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_NOIRE'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MESANGE_NONNETTE'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MILAN_NOIR'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MILAN_ROYAL'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOINEAU_CISALPIN'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOINEAU_DOMESTIQUE'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOINEAU_ESPAGNOL'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOINEAU_FRIQUET'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOINEAU_SOULCIE'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MONTICOLE_BLEU'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MONTICOLE_DE_ROCHE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_ATRICILLE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_BLANCHE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_DE_FRANKLIN'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_DE_SABINE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_MELANOCEPHALE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_PYGMEE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_RIEUSE'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'MOUETTE_TRIDACTYLE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'NETTE_ROUSSE'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'NIVEROLLE_ALPINE'),
((SELECT id FROM family WHERE name = 'UNKNOWN' /* ou LARIDES selon classification */),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'OCEANITE_CULBLANC'),
((SELECT id FROM family WHERE name = 'UNKNOWN' /* ou LARIDES */),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'OCEANITE_DE_CASTRO'),
((SELECT id FROM family WHERE name = 'UNKNOWN' /* ou LARIDES */),
(SELECT id FROM migration_type WHERE name = 'UNKNOWN'), 'OCEANITE_TEMPETE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OEDICNEME_CRIARD'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_A_BEC_COURT'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_CENDREE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_DES_MOISSONS'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_DES_NEIGES'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_NAINE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OIE_RIEUSE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OUETTE_D_EGYPTE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OUTARDE_BARBUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OUTARDE_CANEPETIERE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OUTARDE_DE_MACQUEEN'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'OUTARDE_HOUBARA'),
((SELECT id FROM family WHERE name = 'PANURIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PANURE_A_MOUSTACHES'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PELICAN_BLANC'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PELICAN_FRISE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PELICAN_GRIS'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PERDRIX_BARTAVELLE'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PERDRIX_GRISE'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PERDRIX_ROUGE'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PETIT_GRAVELOT'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PETIT_DUC_SCOPS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PHALAROPE_A_BEC_ETROIT'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PHALAROPE_A_BEC_LARGE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PHRAGMITE_AQUATIQUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PHRAGMITE_DES_JONCS'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_A_DOS_BLANC'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_CENDRE'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_EPEICHE'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_EPEICHETTE'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_MAR'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_NOIR'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_TRIDACTYLE'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIC_VERT'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_BAVARDE'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_GRIECHE_A_POITRINE_ROSE'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_GRIECHE_A_TETE_ROUSSE'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_GRIECHE_ECORCHEUR'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_GRIECHE_GRISE'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIE_GRIECHE_ISABELLE'),
((SELECT id FROM family WHERE name = 'COLUMBIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIGEON_BISET_DOMESTIQUE'),
((SELECT id FROM family WHERE name = 'COLUMBIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIGEON_COLOMBIN'),
((SELECT id FROM family WHERE name = 'COLUMBIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIGEON_RAMIER'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PINSON_DES_ARBRES'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PINSON_DU_NORD'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_A_DOS_OLIVE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_A_GORGE_ROUSSE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_DE_RICHARD'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_DES_ARBRES'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_FARLOUSE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_ROUSSELINE'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PIPIT_SPIONCELLE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLONGEON_A_BEC_BLANC'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLONGEON_ARCTIQUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLONGEON_CATMARIN'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLONGEON_DU_PACIFIQUE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLONGEON_IMBRIN'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLUVIER_ARGENTE'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLUVIER_DORE'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLUVIER_FAUVE'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PLUVIER_GUIGNARD'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_A_GRANDS_SOURCILS'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_BRUN'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_DE_BONELLI'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_DE_HUME'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_DE_PALLAS'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_DE_SCHWARZ'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_DE_SIBERIE'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_FITIS'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_IBERIQUE'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_SIFFLEUR'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_VELOCE'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'POUILLOT_VERDATRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PUFFIN_CENDRE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PUFFIN_DE_SCOPOLI'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PUFFIN_DES_ANGLAIS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PUFFIN_FULIGINEUX'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PUFFIN_YELKOUAN'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'PYGARGUE_A_QUEUE_BLANCHE'),
((SELECT id FROM family WHERE name = 'RALLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'RALE_D_EAU'),
((SELECT id FROM family WHERE name = 'RALLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'RALE_DES_GENETS'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'REMIZ_PENDULINE'),
((SELECT id FROM family WHERE name = 'REGULIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROITELET_A_TRIPLE_BANDEAU'),
((SELECT id FROM family WHERE name = 'REGULIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROITELET_HUPPE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROLLIER_D_EUROPE'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROSELIN_CRAMOISI'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROSELIN_GITHAGINE'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROSSIGNOL_PHILOMELE'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROSSIGNOL_PROGNE'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUGEGORGE_FAMILIER'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUGEQUEUE_A_FRONT_BLANC'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUGEQUEUE_NOIR'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUSSEROLLE_DES_BUISSONS'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUSSEROLLE_EFFARVATTE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUSSEROLLE_ISABELLE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUSSEROLLE_TURDOIDE'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'ROUSSEROLLE_VERDEROLLE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SARCELLE_A_AILES_BLEUES'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SARCELLE_D_ETE'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SARCELLE_D_HIVER'),
((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SARCELLE_MARBREE'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SERIN_CINI'),
((SELECT id FROM family WHERE name = 'SITTIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SITTELLE_TORCHEPOT'),
((SELECT id from family where name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SIZERIN_FLAMME'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SPATULE_BLANCHE'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_ARCTIQUE'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_CASPIENNE'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_CAUGEK'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_DE_DOUGALL'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_HANSEL'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_NAINE'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_PIERREGARIN'),
((SELECT id from family where name = 'LARIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'STERNE_VOYAGEUSE'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'SYRRHAPTE_PARADOXAL'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TADORNE_CASARCA'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TADORNE_DE_BELON'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TALEVE_SULTANE'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TALEVE_VIOLACEE'),
((SELECT id from family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TARIER_DES_PRES'),
((SELECT id from family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TARIER_PATRE'),
((SELECT id from family where name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TARIN_DES_AULNES'),
((SELECT id from family where name = 'PHASIANIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TETRAS_LYRE'),
((SELECT id from family where name = 'TICHODROMIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TICHODROME_ECHELETTE'),
((SELECT id from family where name = 'PICIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TORCOL_FOURMILIER'),
((SELECT id from family where name = 'UNKNOWN'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TOURNEPIERRE_A_COLLIER'),
((SELECT id from family where name = 'COLUMBIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TOURTERELLE_DES_BOIS'),
((SELECT id from family where name = 'COLUMBIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TOURTERELLE_TURQUE'),
((SELECT id from family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TRAQUET_DU_DESERT'),
((SELECT id from family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TRAQUET_MOTTEUX'),
((SELECT id from family where name = 'MUSCICAPIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TRAQUET_OREILLARD'),
((SELECT id from family where name = 'TROGLODYTIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'TROGLODYTE_MIGNON'),
((SELECT id from family where name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VANNEAU_HUPPE'),
((SELECT id from family where name = 'CHARADRIIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VANNEAU_SOCIABLE'),
((SELECT id from family where name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VAUTOUR_FAUVE'),
((SELECT id from family where name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VAUTOUR_MOINE'),
((SELECT id from family where name = 'ACCIPITRIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VAUTOUR_PERCNOPTERE'),
((SELECT id from family where name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VENTURON_MONTAGNARD'),
((SELECT id from family where name = 'FRINGILLIDES'), (SELECT id FROM migration_type WHERE name = 'UNKNOWN'),
'VERDIER_D_EUROPE');
INSERT INTO fetcher(name)
VALUES ('Vogelwarte'),
('chant-oiseaux.fr'),
('oiseaux.net');
INSERT INTO profile(name)
VALUES ('default');
INSERT INTO picture_type (name)
VALUES ('ADULT_NUPTIAL_MALE'),
('ADULT_NUPTIAL_FEMALE'),
('ADULT_NUPTIAL'),
('ADULT_INTERNUPTIAL_MALE'),
('ADULT_INTERNUPTIAL_FEMALE'),
('ADULT_INTERNUPTIAL'),
('ADULT_MALE'),
('ADULT_FEMALE'),
('ADULT'),
('JUVENILE_MALE'),
('JUVENILE_FEMALE'),
('JUVENILE'),
('LIGHT_MORPH'),
('DARK_MORPH'),
('SUB_SPECIES'),
('UNKNOWN');
INSERT INTO sound_type(name)
VALUES ('SONG'),
('CALL'),
('ALARM'),
('FLY_CALL'),
('JUVENILE_CALL'),
('UNKNOWN');
INSERT INTO question_type (name)
VALUES ('PICTURE_EXACT'),
('PICTURE_MULTICHOICE'),
('SOUND_EXACT'),
('SOUND_MULTICHOICE'),
('SOUND_MULTICHOICE_PICTURE');
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,938 @@
INSERT INTO language(name)
VALUES ('FR');
INSERT INTO family_translation(family_id, language_id, translation)
VALUES ((SELECT id FROM family WHERE name = 'ANATIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Anatidés'),
((SELECT id FROM family WHERE name = 'PHASIANIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Phasianidés'),
((SELECT id FROM family WHERE name = 'PODICIPEDIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Podicipédidés'),
((SELECT id FROM family WHERE name = 'CICONIIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Ciconiidés'),
((SELECT id FROM family WHERE name = 'ARDEIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Ardéidés'),
((SELECT id FROM family WHERE name = 'PHALACROCORACIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Phalacrocoracidés'),
((SELECT id FROM family WHERE name = 'ACCIPITRIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Accipitridés'),
((SELECT id FROM family WHERE name = 'RALLIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Rallidés'),
((SELECT id FROM family WHERE name = 'CHARADRIIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Charadriidés'),
((SELECT id FROM family WHERE name = 'SCOLOPACIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Scolopacidés'),
((SELECT id FROM family WHERE name = 'LARIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Laridés'),
((SELECT id FROM family WHERE name = 'COLUMBIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Columbidés'),
((SELECT id FROM family WHERE name = 'CUCULIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Cuculidés'),
((SELECT id FROM family WHERE name = 'TYTONIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Tytonidés'),
((SELECT id FROM family WHERE name = 'STRIGIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Strigidés'),
((SELECT id FROM family WHERE name = 'CAPRIMULGIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Caprimulgidés'),
((SELECT id FROM family WHERE name = 'APODIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Apodidés'),
((SELECT id FROM family WHERE name = 'ALCEDINIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Alcédinidés'),
((SELECT id FROM family WHERE name = 'MEROPIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Méropidés'),
((SELECT id FROM family WHERE name = 'UPUPIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Upupidés'),
((SELECT id FROM family WHERE name = 'PICIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Picidés'),
((SELECT id FROM family WHERE name = 'FALCONIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Falconidés'),
((SELECT id FROM family WHERE name = 'LANIIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Laniidés'),
((SELECT id FROM family WHERE name = 'ORIOLIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Oriolidés'),
((SELECT id FROM family WHERE name = 'CORVIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Corvidés'),
((SELECT id FROM family WHERE name = 'PARIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Paridés'),
((SELECT id FROM family WHERE name = 'PANURIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Panuridés'),
((SELECT id FROM family WHERE name = 'ALAUDIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Alaudidés'),
((SELECT id FROM family WHERE name = 'HIRUNDINIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Hirundinidés'),
((SELECT id FROM family WHERE name = 'AEGITHALIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Aegithalidés'),
((SELECT id FROM family WHERE name = 'PHYLLOSCOPIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Phylloscopidés'),
((SELECT id FROM family WHERE name = 'ACROCEPHALIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Acrocéphalidés'),
((SELECT id FROM family WHERE name = 'LOCUSTELLIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Locustellidés'),
((SELECT id FROM family WHERE name = 'SYLVIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Sylvidés'),
((SELECT id FROM family WHERE name = 'REGULIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Régulidés'),
((SELECT id FROM family WHERE name = 'TROGLODYTIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Troglodytidés'),
((SELECT id FROM family WHERE name = 'SITTIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Sittidés'),
((SELECT id FROM family WHERE name = 'TICHODROMIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Tichodromidés'),
((SELECT id FROM family WHERE name = 'CERTHIIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Certhiidés'),
((SELECT id FROM family WHERE name = 'STURNIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Sturnidés'),
((SELECT id FROM family WHERE name = 'TURDIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Turdidés'),
((SELECT id FROM family WHERE name = 'MUSCICAPIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Muscicapidés'),
((SELECT id FROM family WHERE name = 'CINCLIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Cinclidés'),
((SELECT id FROM family WHERE name = 'PASSERIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Passéridés'),
((SELECT id FROM family WHERE name = 'PRUNELLIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Prunellidés'),
((SELECT id FROM family WHERE name = 'MOTACILLIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Motacillidés'),
((SELECT id FROM family WHERE name = 'FRINGILLIDES'), (SELECT id FROM language WHERE name = 'FR'),
'Fringillidés'),
((SELECT id FROM family WHERE name = 'EMBERIZIDES'), (SELECT id FROM language WHERE name = 'FR'), 'Emberizidés'),
((SELECT id FROM family WHERE name = 'UNKNOWN'), (SELECT id FROM language WHERE name = 'FR'), 'Inconnu');
INSERT INTO bird_translation(bird_id, language_id, translation)
VALUES ((SELECT id FROM bird WHERE name = 'ACCENTEUR_ALPIN'), (SELECT id FROM language WHERE name = 'FR'),
'Accenteur alpin'),
((SELECT id FROM bird WHERE name = 'ACCENTEUR_MOUCHET'), (SELECT id FROM language WHERE name = 'FR'),
'Accenteur mouchet'),
((SELECT id FROM bird WHERE name = 'AGROBATE_ROUX'), (SELECT id FROM language WHERE name = 'FR'),
'Agrobate roux'),
((SELECT id FROM bird WHERE name = 'AIGLE_BOTTE'), (SELECT id FROM language WHERE name = 'FR'), 'Aigle botté'),
((SELECT id FROM bird WHERE name = 'AIGLE_CRIARD'), (SELECT id FROM language WHERE name = 'FR'), 'Aigle criard'),
((SELECT id FROM bird WHERE name = 'AIGLE_POMARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Aigle pomarin'),
((SELECT id FROM bird WHERE name = 'AIGLE_ROYAL'), (SELECT id FROM language WHERE name = 'FR'), 'Aigle royal'),
((SELECT id FROM bird WHERE name = 'AIGRETTE_GARZETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Aigrette garzette'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_CALANDRE'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette calandre'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_CALANDRELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette calandrelle'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_DES_CHAMPS'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette des champs'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_HAUSSECOL'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette haussecol'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_LEUCOPTERE'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette leucoptère'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_LULU'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette lulu'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_MONTICOLE'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette monticole'),
((SELECT id FROM bird WHERE name = 'ALOUETTE_PISPOLETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Alouette pispolette'),
((SELECT id FROM bird WHERE name = 'AUTOUR_DES_PALOMBES'), (SELECT id FROM language WHERE name = 'FR'),
'Autour des palombes'),
((SELECT id FROM bird WHERE name = 'AVOCETTE_ELEGANTE'), (SELECT id FROM language WHERE name = 'FR'),
'Avocette élégante'),
((SELECT id FROM bird WHERE name = 'BALBUZARD_PECHEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Balbuzard pêcheur'),
((SELECT id FROM bird WHERE name = 'BARGE_A_QUEUE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Barge à queue noire'),
((SELECT id FROM bird WHERE name = 'BARGE_ROUSSE'), (SELECT id FROM language WHERE name = 'FR'), 'Barge rousse'),
((SELECT id FROM bird WHERE name = 'BEC_CROISE_DES_SAPINS'), (SELECT id FROM language WHERE name = 'FR'),
'Bec-croisé des sapins'),
((SELECT id FROM bird WHERE name = 'BECASSE_DES_BOIS'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasse des bois'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_COCORLI'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau cocorli'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_DE_BONAPARTE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau de Bonaparte'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_DE_TEMMINCK'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau de Temminck'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_FALCINELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau falcinelle'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_MAUBECHE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau maubèche'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_MINUTE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau minute'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_ROUSSET'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau rousset'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_SANDERLING'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau sanderling'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_TACHETE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau tacheté'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_VARIABLE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau variable'),
((SELECT id FROM bird WHERE name = 'BECASSEAU_VIOLET'), (SELECT id FROM language WHERE name = 'FR'),
'Bécasseau violet'),
((SELECT id FROM bird WHERE name = 'BECASSINE_DES_MARAIS'), (SELECT id FROM language WHERE name = 'FR'),
'Bécassine des marais'),
((SELECT id FROM bird WHERE name = 'BECASSINE_DOUBLE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécassine double'),
((SELECT id FROM bird WHERE name = 'BECASSINE_SOURDE'), (SELECT id FROM language WHERE name = 'FR'),
'Bécassine sourde'),
((SELECT id FROM bird WHERE name = 'BERGERONNETTE_CITRINE'), (SELECT id FROM language WHERE name = 'FR'),
'Bergeronnette citrine'),
((SELECT id FROM bird WHERE name = 'BERGERONNETTE_DES_RUISSEAUX'), (SELECT id FROM language WHERE name = 'FR'),
'Bergeronnette des ruisseaux'),
((SELECT id FROM bird WHERE name = 'BERGERONNETTE_GRISE'), (SELECT id FROM language WHERE name = 'FR'),
'Bergeronnette grise'),
((SELECT id FROM bird WHERE name = 'BERGERONNETTE_PRINTANIERE'), (SELECT id FROM language WHERE name = 'FR'),
'Bergeronnette printanière'),
((SELECT id FROM bird WHERE name = 'BERNACHE_A_COU_ROUX'), (SELECT id FROM language WHERE name = 'FR'),
'Bernache à cou roux'),
((SELECT id FROM bird WHERE name = 'BERNACHE_CRAVANT'), (SELECT id FROM language WHERE name = 'FR'),
'Bernache cravant'),
((SELECT id FROM bird WHERE name = 'BERNACHE_DU_CANADA'), (SELECT id FROM language WHERE name = 'FR'),
'Bernache du Canada'),
((SELECT id FROM bird WHERE name = 'BERNACHE_NONNETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Bernache nonnette'),
((SELECT id FROM bird WHERE name = 'BIHOREAU_GRIS'), (SELECT id FROM language WHERE name = 'FR'),
'Bihoreau gris'),
((SELECT id FROM bird WHERE name = 'BLONGIOS_NAIN'), (SELECT id FROM language WHERE name = 'FR'),
'Blongios nain'),
((SELECT id FROM bird WHERE name = 'BONDREE_APIVORE'), (SELECT id FROM language WHERE name = 'FR'),
'Bondrée apivore'),
((SELECT id FROM bird WHERE name = 'BOUSCARLE_DE_CETTI'), (SELECT id FROM language WHERE name = 'FR'),
'Bouscarle de Cetti'),
((SELECT id FROM bird WHERE name = 'BOUVREUIL_PIVOINE'), (SELECT id FROM language WHERE name = 'FR'),
'Bouvreuil pivoine'),
((SELECT id FROM bird WHERE name = 'BRUANT_A_CALOTTE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant à calotte blanche'),
((SELECT id FROM bird WHERE name = 'BRUANT_CHANTEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant chanteur'),
((SELECT id FROM bird WHERE name = 'BRUANT_DES_NEIGES'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant des neiges'),
((SELECT id FROM bird WHERE name = 'BRUANT_DES_ROSEAUX'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant des roseaux'),
((SELECT id FROM bird WHERE name = 'BRUANT_FOU'), (SELECT id FROM language WHERE name = 'FR'), 'Bruant fou'),
((SELECT id FROM bird WHERE name = 'BRUANT_JAUNE'), (SELECT id FROM language WHERE name = 'FR'), 'Bruant jaune'),
((SELECT id FROM bird WHERE name = 'BRUANT_LAPON'), (SELECT id FROM language WHERE name = 'FR'), 'Bruant lapon'),
((SELECT id FROM bird WHERE name = 'BRUANT_MELANOCEPHALE'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant mélanocéphale'),
((SELECT id FROM bird WHERE name = 'BRUANT_NAIN'), (SELECT id FROM language WHERE name = 'FR'), 'Bruant nain'),
((SELECT id FROM bird WHERE name = 'BRUANT_ORTOLAN'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant ortolan'),
((SELECT id FROM bird WHERE name = 'BRUANT_PROYER'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant proyer'),
((SELECT id FROM bird WHERE name = 'BRUANT_RUSTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Bruant rustique'),
((SELECT id FROM bird WHERE name = 'BRUANT_ZIZI'), (SELECT id FROM language WHERE name = 'FR'), 'Bruant zizi'),
((SELECT id FROM bird WHERE name = 'BUSARD_CENDRE'), (SELECT id FROM language WHERE name = 'FR'),
'Busard cendré'),
((SELECT id FROM bird WHERE name = 'BUSARD_DES_ROSEAUX'), (SELECT id FROM language WHERE name = 'FR'),
'Busard des roseaux'),
((SELECT id FROM bird WHERE name = 'BUSARD_PALE'), (SELECT id FROM language WHERE name = 'FR'), 'Busard pâle'),
((SELECT id FROM bird WHERE name = 'BUSARD_SAINT_MARTIN'), (SELECT id FROM language WHERE name = 'FR'),
'Busard Saint-Martin'),
((SELECT id FROM bird WHERE name = 'BUSE_FEROCE'), (SELECT id FROM language WHERE name = 'FR'), 'Buse féroce'),
((SELECT id FROM bird WHERE name = 'BUSE_PATTUE'), (SELECT id FROM language WHERE name = 'FR'), 'Buse pattue'),
((SELECT id FROM bird WHERE name = 'BUSE_VARIABLE'), (SELECT id FROM language WHERE name = 'FR'),
'Buse variable'),
((SELECT id FROM bird WHERE name = 'BUTOR_ETOILE'), (SELECT id FROM language WHERE name = 'FR'), 'Butor étoilé'),
((SELECT id FROM bird WHERE name = 'CAILLE_DES_BLES'), (SELECT id FROM language WHERE name = 'FR'),
'Caille des blés'),
((SELECT id FROM bird WHERE name = 'CANARD_CAROLIN'), (SELECT id FROM language WHERE name = 'FR'),
'Canard carolin'),
((SELECT id FROM bird WHERE name = 'CANARD_CHIPEAU'), (SELECT id FROM language WHERE name = 'FR'),
'Canard chipeau'),
((SELECT id FROM bird WHERE name = 'CANARD_COLVERT'), (SELECT id FROM language WHERE name = 'FR'),
'Canard colvert'),
((SELECT id FROM bird WHERE name = 'CANARD_MANDARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Canard mandarin'),
((SELECT id FROM bird WHERE name = 'CANARD_PILET'), (SELECT id FROM language WHERE name = 'FR'), 'Canard pilet'),
((SELECT id FROM bird WHERE name = 'CANARD_SIFFLEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Canard siffleur'),
((SELECT id FROM bird WHERE name = 'CANARD_SOUCHET'), (SELECT id FROM language WHERE name = 'FR'),
'Canard souchet'),
((SELECT id FROM bird WHERE name = 'CASSENOIX_MOUCHETE'), (SELECT id FROM language WHERE name = 'FR'),
'Cassenoix moucheté'),
((SELECT id FROM bird WHERE name = 'CHARDONNERET_ELEGANT'), (SELECT id FROM language WHERE name = 'FR'),
'Chardonneret élégant'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_ABOYEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier aboyeur'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_ARLEQUIN'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier arlequin'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_BARGETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier bargette'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_CULBLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier cul-blanc'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_GAMBETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier gambette'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_GRIVELE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier grivelé'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_GUIGNETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier guignette'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_STAGNATILE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier stagnatile'),
((SELECT id FROM bird WHERE name = 'CHEVALIER_SYLVAIN'), (SELECT id FROM language WHERE name = 'FR'),
'Chevalier sylvain'),
((SELECT id FROM bird WHERE name = 'CHEVECHE_D_ATHENA'), (SELECT id FROM language WHERE name = 'FR'),
'Chevêche d''Athéna'),
((SELECT id FROM bird WHERE name = 'CHEVECHETTE_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Chevêchette d''Europe'),
((SELECT id FROM bird WHERE name = 'CHOCARD_A_BEC_JAUNE'), (SELECT id FROM language WHERE name = 'FR'),
'Chocard à bec jaune'),
((SELECT id FROM bird WHERE name = 'CHOUCAS_DES_TOURS'), (SELECT id FROM language WHERE name = 'FR'),
'Choucas des tours'),
((SELECT id FROM bird WHERE name = 'CHOUETTE_DE_TENGMALM'), (SELECT id FROM language WHERE name = 'FR'),
'Chouette de Tengmalm'),
((SELECT id FROM bird WHERE name = 'CHOUETTE_EPERVIERE'), (SELECT id FROM language WHERE name = 'FR'),
'Chouette épervière'),
((SELECT id FROM bird WHERE name = 'CHOUETTE_HULOTTE'), (SELECT id FROM language WHERE name = 'FR'),
'Chouette hulotte'),
((SELECT id FROM bird WHERE name = 'CIGOGNE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Cigogne blanche'),
((SELECT id FROM bird WHERE name = 'CIGOGNE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Cigogne noire'),
((SELECT id FROM bird WHERE name = 'CINCLE_PLONGEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Cincle plongeur'),
((SELECT id FROM bird WHERE name = 'CIRCAETE_JEAN_LE_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Circaète Jean-le-Blanc'),
((SELECT id FROM bird WHERE name = 'CISTICOLE_DES_JONCS'), (SELECT id FROM language WHERE name = 'FR'),
'Cisticole des joncs'),
((SELECT id FROM bird WHERE name = 'COCHEVIS_HUPPE'), (SELECT id FROM language WHERE name = 'FR'),
'Cochevis huppé'),
((SELECT id FROM bird WHERE name = 'COMBATTANT_VARIE'), (SELECT id FROM language WHERE name = 'FR'),
'Combattant varié'),
((SELECT id FROM bird WHERE name = 'CORBEAU_FREUX'), (SELECT id FROM language WHERE name = 'FR'),
'Corbeau freux'),
((SELECT id FROM bird WHERE name = 'CORMORAN_HUPPE'), (SELECT id FROM language WHERE name = 'FR'),
'Cormoran huppé'),
((SELECT id FROM bird WHERE name = 'CORMORAN_PYGMEE'), (SELECT id FROM language WHERE name = 'FR'),
'Cormoran pygmée'),
((SELECT id FROM bird WHERE name = 'CORNEILLE_MANTELEE'), (SELECT id FROM language WHERE name = 'FR'),
'Corneille mantelée'),
((SELECT id FROM bird WHERE name = 'CORNEILLE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Corneille noire'),
((SELECT id FROM bird WHERE name = 'COUCOU_GEAI'), (SELECT id FROM language WHERE name = 'FR'), 'Coucou geai'),
((SELECT id FROM bird WHERE name = 'COUCOU_GRIS'), (SELECT id FROM language WHERE name = 'FR'), 'Coucou gris'),
((SELECT id FROM bird WHERE name = 'COURLIS_A_BEC_GRELE'), (SELECT id FROM language WHERE name = 'FR'),
'Courlis à bec grêle'),
((SELECT id FROM bird WHERE name = 'COURLIS_CENDRE'), (SELECT id FROM language WHERE name = 'FR'),
'Courlis cendré'),
((SELECT id FROM bird WHERE name = 'COURLIS_CORLIEU'), (SELECT id FROM language WHERE name = 'FR'),
'Courlis corlieu'),
((SELECT id FROM bird WHERE name = 'COURVITE_ISABELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Courvite isabelle'),
((SELECT id FROM bird WHERE name = 'CRABIER_CHEVELU'), (SELECT id FROM language WHERE name = 'FR'),
'Crabier chevelu'),
((SELECT id FROM bird WHERE name = 'CRAVE_A_BEC_ROUGE'), (SELECT id FROM language WHERE name = 'FR'),
'Crave à bec rouge'),
((SELECT id FROM bird WHERE name = 'CYGNE_CHANTEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Cygne chanteur'),
((SELECT id FROM bird WHERE name = 'CYGNE_DE_BEWICK'), (SELECT id FROM language WHERE name = 'FR'),
'Cygne de Bewick'),
((SELECT id FROM bird WHERE name = 'CYGNE_TUBERCULE'), (SELECT id FROM language WHERE name = 'FR'),
'Cygne tuberculé'),
((SELECT id FROM bird WHERE name = 'DURBEC_DES_SAPINS'), (SELECT id FROM language WHERE name = 'FR'),
'Durbec des sapins'),
((SELECT id FROM bird WHERE name = 'ECHASSE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Échasse blanche'),
((SELECT id FROM bird WHERE name = 'EFFRAIE_DES_CLOCHERS'), (SELECT id FROM language WHERE name = 'FR'),
'Effraie des clochers'),
((SELECT id FROM bird WHERE name = 'EIDER_A_DUVET'), (SELECT id FROM language WHERE name = 'FR'),
'Eider à duvet'),
((SELECT id FROM bird WHERE name = 'ELANION_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Élanion blanc'),
((SELECT id FROM bird WHERE name = 'ENGOULEVENT_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Engoulevent d''Europe'),
((SELECT id FROM bird WHERE name = 'EPERVIER_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Épervier d''Europe'),
((SELECT id FROM bird WHERE name = 'ERISMATURE_A_TETE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Érismature à tête blanche'),
((SELECT id FROM bird WHERE name = 'ERISMATURE_ROUSSE'), (SELECT id FROM language WHERE name = 'FR'),
'Érismature rousse'),
((SELECT id FROM bird WHERE name = 'ETOURNEAU_ROSELIN'), (SELECT id FROM language WHERE name = 'FR'),
'Étourneau roselin'),
((SELECT id FROM bird WHERE name = 'ETOURNEAU_SANSONNET'), (SELECT id FROM language WHERE name = 'FR'),
'Étourneau sansonnet'),
((SELECT id FROM bird WHERE name = 'ETOURNEAU_UNICOLORE'), (SELECT id FROM language WHERE name = 'FR'),
'Étourneau unicolore'),
((SELECT id FROM bird WHERE name = 'FAISAN_DE_COLCHIDE'), (SELECT id FROM language WHERE name = 'FR'),
'Faisan de Colchide'),
((SELECT id FROM bird WHERE name = 'FAUCON_CRECERELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon crécerelle'),
((SELECT id FROM bird WHERE name = 'FAUCON_CRECERELLETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon crécerellette'),
((SELECT id FROM bird WHERE name = 'FAUCON_D_ELEONORE'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon d''Éléonore'),
((SELECT id FROM bird WHERE name = 'FAUCON_EMERILLON'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon émerillon'),
((SELECT id FROM bird WHERE name = 'FAUCON_GERFAUT'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon gerfaut'),
((SELECT id FROM bird WHERE name = 'FAUCON_HOBEREAU'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon hobereau'),
((SELECT id FROM bird WHERE name = 'FAUCON_KOBEZ'), (SELECT id FROM language WHERE name = 'FR'), 'Faucon kobez'),
((SELECT id FROM bird WHERE name = 'FAUCON_PELERIN'), (SELECT id FROM language WHERE name = 'FR'),
'Faucon pèlerin'),
((SELECT id FROM bird WHERE name = 'FAUCON_SACRE'), (SELECT id FROM language WHERE name = 'FR'), 'Faucon sacre'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_A_LUNETTES'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette à lunettes'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_A_TETE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette à tête noire'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_BABILLARDE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette babillarde'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_DES_JARDINS'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette des jardins'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_EPERVIERE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette épervière'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_GRISETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette grisette'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_MELANOCEPHALE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette mélanocéphale'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_ORPHEE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette orphée'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_PASSERINETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette passerinette'),
((SELECT id FROM bird WHERE name = 'FAUVETTE_PITCHOU'), (SELECT id FROM language WHERE name = 'FR'),
'Fauvette pitchou'),
((SELECT id FROM bird WHERE name = 'FLAMANT_ROSE'), (SELECT id FROM language WHERE name = 'FR'), 'Flamant rose'),
((SELECT id FROM bird WHERE name = 'FOU_DE_BASSAN'), (SELECT id FROM language WHERE name = 'FR'),
'Fou de Bassan'),
((SELECT id FROM bird WHERE name = 'FOULQUE_MACROULE'), (SELECT id FROM language WHERE name = 'FR'),
'Foulque macroule'),
((SELECT id FROM bird WHERE name = 'FULIGULE_A_BEC_CERCLE'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule à bec cerclé'),
((SELECT id FROM bird WHERE name = 'FULIGULE_A_TETE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule à tête noire'),
((SELECT id FROM bird WHERE name = 'FULIGULE_MILOUIN'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule milouin'),
((SELECT id FROM bird WHERE name = 'FULIGULE_MILOUINAN'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule milouinan'),
((SELECT id FROM bird WHERE name = 'FULIGULE_MORILLON'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule morillon'),
((SELECT id FROM bird WHERE name = 'FULIGULE_NYROCA'), (SELECT id FROM language WHERE name = 'FR'),
'Fuligule nyroca'),
((SELECT id FROM bird WHERE name = 'GALLINULE_POULE_D_EAU'), (SELECT id FROM language WHERE name = 'FR'),
'Gallinule poule-d''eau'),
((SELECT id FROM bird WHERE name = 'GARROT_A_OEIL_D_OR'), (SELECT id FROM language WHERE name = 'FR'),
'Garrot à oeil d''or'),
((SELECT id FROM bird WHERE name = 'GEAI_DES_CHENES'), (SELECT id FROM language WHERE name = 'FR'),
'Geai des chênes'),
((SELECT id FROM bird WHERE name = 'GELINOTTE_DES_BOIS'), (SELECT id FROM language WHERE name = 'FR'),
'Gélinotte des bois'),
((SELECT id FROM bird WHERE name = 'GLAREOLE_A_AILES_NOIRES'), (SELECT id FROM language WHERE name = 'FR'),
'Glaréole à ailes noires'),
((SELECT id FROM bird WHERE name = 'GLAREOLE_A_COLLIER'), (SELECT id FROM language WHERE name = 'FR'),
'Glaréole à collier'),
((SELECT id FROM bird WHERE name = 'GOBEMOUCHE_A_COLLIER'), (SELECT id FROM language WHERE name = 'FR'),
'Gobemouche à collier'),
((SELECT id FROM bird WHERE name = 'GOBEMOUCHE_A_DEMI_COLLIER'), (SELECT id FROM language WHERE name = 'FR'),
'Gobemouche à demi-collier'),
((SELECT id FROM bird WHERE name = 'GOBEMOUCHE_GRIS'), (SELECT id FROM language WHERE name = 'FR'),
'Gobemouche gris'),
((SELECT id FROM bird WHERE name = 'GOBEMOUCHE_NAIN'), (SELECT id FROM language WHERE name = 'FR'),
'Gobemouche nain'),
((SELECT id FROM bird WHERE name = 'GOBEMOUCHE_NOIR'), (SELECT id FROM language WHERE name = 'FR'),
'Gobemouche noir'),
((SELECT id FROM bird WHERE name = 'GOELAND_A_AILES_BLANCHES'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland à ailes blanches'),
((SELECT id FROM bird WHERE name = 'GOELAND_ARGENTE'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland argenté'),
((SELECT id FROM bird WHERE name = 'GOELAND_BOURGMESTRE'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland bourgmestre'),
((SELECT id FROM bird WHERE name = 'GOELAND_BRUN'), (SELECT id FROM language WHERE name = 'FR'), 'Goéland brun'),
((SELECT id FROM bird WHERE name = 'GOELAND_CENDRE'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland cendré'),
((SELECT id FROM bird WHERE name = 'GOELAND_D_AUDOUIN'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland d''Audouin'),
((SELECT id FROM bird WHERE name = 'GOELAND_LEUCOPHEE'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland leucophée'),
((SELECT id FROM bird WHERE name = 'GOELAND_MARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland marin'),
((SELECT id FROM bird WHERE name = 'GOELAND_PONTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland pontique'),
((SELECT id FROM bird WHERE name = 'GOELAND_RAILLEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Goéland railleur'),
((SELECT id FROM bird WHERE name = 'GORGEBLEUE_A_MIROIR'), (SELECT id FROM language WHERE name = 'FR'),
'Gorgebleue à miroir'),
((SELECT id FROM bird WHERE name = 'GRAND_CORBEAU'), (SELECT id FROM language WHERE name = 'FR'),
'Grand Corbeau'),
((SELECT id FROM bird WHERE name = 'GRAND_CORMORAN'), (SELECT id FROM language WHERE name = 'FR'),
'Grand Cormoran'),
((SELECT id FROM bird WHERE name = 'GRAND_GRAVELOT'), (SELECT id FROM language WHERE name = 'FR'),
'Grand Gravelot'),
((SELECT id FROM bird WHERE name = 'GRAND_LABBE'), (SELECT id FROM language WHERE name = 'FR'), 'Grand Labbe'),
((SELECT id FROM bird WHERE name = 'GRAND_TETRAS'), (SELECT id FROM language WHERE name = 'FR'), 'Grand Tétras'),
((SELECT id FROM bird WHERE name = 'GRAND_DUC_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Grand-duc d''Europe'),
((SELECT id FROM bird WHERE name = 'GRANDE_AIGRETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Grande Aigrette'),
((SELECT id FROM bird WHERE name = 'GRAVELOT_A_COLLIER_INTERROMPU'), (SELECT id FROM language WHERE name = 'FR'),
'Gravelot à collier interrompu'),
((SELECT id FROM bird WHERE name = 'GRAVELOT_KILDIR'), (SELECT id FROM language WHERE name = 'FR'),
'Gravelot kildir'),
((SELECT id FROM bird WHERE name = 'GREBE_A_COU_NOIR'), (SELECT id FROM language WHERE name = 'FR'),
'Grèbe à cou noir'),
((SELECT id FROM bird WHERE name = 'GREBE_CASTAGNEUX'), (SELECT id FROM language WHERE name = 'FR'),
'Grèbe castagneux'),
((SELECT id FROM bird WHERE name = 'GREBE_ESCLAVON'), (SELECT id FROM language WHERE name = 'FR'),
'Grèbe esclavon'),
((SELECT id FROM bird WHERE name = 'GREBE_HUPPE'), (SELECT id FROM language WHERE name = 'FR'), 'Grèbe huppé'),
((SELECT id FROM bird WHERE name = 'GREBE_JOUGRIS'), (SELECT id FROM language WHERE name = 'FR'),
'Grèbe jougris'),
((SELECT id FROM bird WHERE name = 'GRIMPEREAU_DES_BOIS'), (SELECT id FROM language WHERE name = 'FR'),
'Grimpereau des bois'),
((SELECT id FROM bird WHERE name = 'GRIMPEREAU_DES_JARDINS'), (SELECT id FROM language WHERE name = 'FR'),
'Grimpereau des jardins'),
((SELECT id FROM bird WHERE name = 'GRIVE_DE_SIBERIE'), (SELECT id FROM language WHERE name = 'FR'),
'Grive de Sibérie'),
((SELECT id FROM bird WHERE name = 'GRIVE_DRAINE'), (SELECT id FROM language WHERE name = 'FR'), 'Grive draine'),
((SELECT id FROM bird WHERE name = 'GRIVE_LITORNE'), (SELECT id FROM language WHERE name = 'FR'),
'Grive litorne'),
((SELECT id FROM bird WHERE name = 'GRIVE_MAUVIS'), (SELECT id FROM language WHERE name = 'FR'), 'Grive mauvis'),
((SELECT id FROM bird WHERE name = 'GRIVE_MUSICIENNE'), (SELECT id FROM language WHERE name = 'FR'),
'Grive musicienne'),
((SELECT id FROM bird WHERE name = 'GROSBEC_CASSE_NOYAUX'), (SELECT id FROM language WHERE name = 'FR'),
'Grosbec casse-noyaux'),
((SELECT id FROM bird WHERE name = 'GRUE_CENDREE'), (SELECT id FROM language WHERE name = 'FR'), 'Grue cendrée'),
((SELECT id FROM bird WHERE name = 'GUEPIER_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Guêpier d''Europe'),
((SELECT id FROM bird WHERE name = 'GUEPIER_DE_PERSE'), (SELECT id FROM language WHERE name = 'FR'),
'Guêpier de Perse'),
((SELECT id FROM bird WHERE name = 'GUIFETTE_LEUCOPTERE'), (SELECT id FROM language WHERE name = 'FR'),
'Guifette leucoptère'),
((SELECT id FROM bird WHERE name = 'GUIFETTE_MOUSTAC'), (SELECT id FROM language WHERE name = 'FR'),
'Guifette moustac'),
((SELECT id FROM bird WHERE name = 'GUIFETTE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Guifette noire'),
((SELECT id FROM bird WHERE name = 'GUILLEMOT_A_LONG_BEC'), (SELECT id FROM language WHERE name = 'FR'),
'Guillemot à long bec'),
((SELECT id FROM bird WHERE name = 'GUILLEMOT_DE_TROIL'), (SELECT id FROM language WHERE name = 'FR'),
'Guillemot de Troïl'),
((SELECT id FROM bird WHERE name = 'GYPAETE_BARBU'), (SELECT id FROM language WHERE name = 'FR'),
'Gypaète barbu'),
((SELECT id FROM bird WHERE name = 'HARELDE_BOREALE'), (SELECT id FROM language WHERE name = 'FR'),
'Harelde boréale'),
((SELECT id FROM bird WHERE name = 'HARLE_BIEVRE'), (SELECT id FROM language WHERE name = 'FR'), 'Harle bièvre'),
((SELECT id FROM bird WHERE name = 'HARLE_HUPPE'), (SELECT id FROM language WHERE name = 'FR'), 'Harle huppé'),
((SELECT id FROM bird WHERE name = 'HARLE_PIETTE'), (SELECT id FROM language WHERE name = 'FR'), 'Harle piette'),
((SELECT id FROM bird WHERE name = 'HERON_CENDRE'), (SELECT id FROM language WHERE name = 'FR'), 'Héron cendré'),
((SELECT id FROM bird WHERE name = 'HERON_GARDE_BOEUFS'), (SELECT id FROM language WHERE name = 'FR'),
'Héron garde-boeufs'),
((SELECT id FROM bird WHERE name = 'HERON_POURPRE'), (SELECT id FROM language WHERE name = 'FR'),
'Héron pourpré'),
((SELECT id FROM bird WHERE name = 'HIBOU_DES_MARAIS'), (SELECT id FROM language WHERE name = 'FR'),
'Hibou des marais'),
((SELECT id FROM bird WHERE name = 'HIBOU_MOYEN_DUC'), (SELECT id FROM language WHERE name = 'FR'),
'Hibou moyen-duc'),
((SELECT id FROM bird WHERE name = 'HIRONDELLE_DE_FENETRE'), (SELECT id FROM language WHERE name = 'FR'),
'Hirondelle de fenêtre'),
((SELECT id FROM bird WHERE name = 'HIRONDELLE_DE_RIVAGE'), (SELECT id FROM language WHERE name = 'FR'),
'Hirondelle de rivage'),
((SELECT id FROM bird WHERE name = 'HIRONDELLE_DE_ROCHERS'), (SELECT id FROM language WHERE name = 'FR'),
'Hirondelle de rochers'),
((SELECT id FROM bird WHERE name = 'HIRONDELLE_ROUSSELINE'), (SELECT id FROM language WHERE name = 'FR'),
'Hirondelle rousseline'),
((SELECT id FROM bird WHERE name = 'HIRONDELLE_RUSTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Hirondelle rustique'),
((SELECT id FROM bird WHERE name = 'HUITRIER_PIE'), (SELECT id FROM language WHERE name = 'FR'), 'Huîtrier pie'),
((SELECT id FROM bird WHERE name = 'HUPPE_FASCIEE'), (SELECT id FROM language WHERE name = 'FR'),
'Huppe fasciée'),
((SELECT id FROM bird WHERE name = 'HYPOLAIS_BOTTEE'), (SELECT id FROM language WHERE name = 'FR'),
'Hypolaïs bottée'),
((SELECT id FROM bird WHERE name = 'HYPOLAIS_ICTERINE'), (SELECT id FROM language WHERE name = 'FR'),
'Hypolaïs ictérine'),
((SELECT id FROM bird WHERE name = 'HYPOLAIS_POLYGLOTTE'), (SELECT id FROM language WHERE name = 'FR'),
'Hypolaïs polyglotte'),
((SELECT id FROM bird WHERE name = 'IBIS_CHAUVE'), (SELECT id FROM language WHERE name = 'FR'), 'Ibis chauve'),
((SELECT id FROM bird WHERE name = 'IBIS_FALCINELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Ibis falcinelle'),
((SELECT id FROM bird WHERE name = 'IBIS_SACRE'), (SELECT id FROM language WHERE name = 'FR'), 'Ibis sacré'),
((SELECT id FROM bird WHERE name = 'IRANIE_A_GORGE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Iranie à gorge blanche'),
((SELECT id FROM bird WHERE name = 'JASEUR_BOREAL'), (SELECT id FROM language WHERE name = 'FR'),
'Jaseur boréal'),
((SELECT id FROM bird WHERE name = 'LABBE_A_LONGUE_QUEUE'), (SELECT id FROM language WHERE name = 'FR'),
'Labbe à longue queue'),
((SELECT id FROM bird WHERE name = 'LABBE_PARASITE'), (SELECT id FROM language WHERE name = 'FR'),
'Labbe parasite'),
((SELECT id FROM bird WHERE name = 'LABBE_POMARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Labbe pomarin'),
((SELECT id FROM bird WHERE name = 'LAGOPEDE_ALPIN'), (SELECT id FROM language WHERE name = 'FR'),
'Lagopède alpin'),
((SELECT id FROM bird WHERE name = 'LINOTTE_A_BEC_JAUNE'), (SELECT id FROM language WHERE name = 'FR'),
'Linotte à bec jaune'),
((SELECT id FROM bird WHERE name = 'LINOTTE_MELODIEUSE'), (SELECT id FROM language WHERE name = 'FR'),
'Linotte mélodieuse'),
((SELECT id FROM bird WHERE name = 'LOCUSTELLE_FLUVIATILE'), (SELECT id FROM language WHERE name = 'FR'),
'Locustelle fluviatile'),
((SELECT id FROM bird WHERE name = 'LOCUSTELLE_LUSCINIOIDE'), (SELECT id FROM language WHERE name = 'FR'),
'Locustelle luscinioïde'),
((SELECT id FROM bird WHERE name = 'LOCUSTELLE_TACHETEE'), (SELECT id FROM language WHERE name = 'FR'),
'Locustelle tachetée'),
((SELECT id FROM bird WHERE name = 'LORIOT_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Loriot d''Europe'),
((SELECT id FROM bird WHERE name = 'LUSCINIOLE_A_MOUSTACHES'), (SELECT id FROM language WHERE name = 'FR'),
'Lusciniole à moustaches'),
((SELECT id FROM bird WHERE name = 'MACREUSE_BRUNE'), (SELECT id FROM language WHERE name = 'FR'),
'Macreuse brune'),
((SELECT id FROM bird WHERE name = 'MACREUSE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Macreuse noire'),
((SELECT id FROM bird WHERE name = 'MAROUETTE_DE_BAILLON'), (SELECT id FROM language WHERE name = 'FR'),
'Marouette de Baillon'),
((SELECT id FROM bird WHERE name = 'MAROUETTE_PONCTUEE'), (SELECT id FROM language WHERE name = 'FR'),
'Marouette ponctuée'),
((SELECT id FROM bird WHERE name = 'MAROUETTE_POUSSIN'), (SELECT id FROM language WHERE name = 'FR'),
'Marouette poussin'),
((SELECT id FROM bird WHERE name = 'MARTIN_PECHEUR_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Martin-pêcheur d''Europe'),
((SELECT id FROM bird WHERE name = 'MARTINET_A_VENTRE_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Martinet à ventre blanc'),
((SELECT id FROM bird WHERE name = 'MARTINET_NOIR'), (SELECT id FROM language WHERE name = 'FR'),
'Martinet noir'),
((SELECT id FROM bird WHERE name = 'MARTINET_PALE'), (SELECT id FROM language WHERE name = 'FR'),
'Martinet pâle'),
((SELECT id FROM bird WHERE name = 'MERLE_A_PLASTRON'), (SELECT id FROM language WHERE name = 'FR'),
'Merle à plastron'),
((SELECT id FROM bird WHERE name = 'MERLE_NOIR'), (SELECT id FROM language WHERE name = 'FR'), 'Merle noir'),
((SELECT id FROM bird WHERE name = 'MESANGE_A_LONGUE_QUEUE'), (SELECT id FROM language WHERE name = 'FR'),
'Orite à longue queue'),
((SELECT id FROM bird WHERE name = 'MESANGE_BLEUE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange bleue'),
((SELECT id FROM bird WHERE name = 'MESANGE_BOREALE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange boréale'),
((SELECT id FROM bird WHERE name = 'MESANGE_CHARBONNIERE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange charbonnière'),
((SELECT id FROM bird WHERE name = 'MESANGE_HUPPEE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange huppée'),
((SELECT id FROM bird WHERE name = 'MESANGE_NOIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange noire'),
((SELECT id FROM bird WHERE name = 'MESANGE_NONNETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange nonnette'),
((SELECT id FROM bird WHERE name = 'MILAN_NOIR'), (SELECT id FROM language WHERE name = 'FR'), 'Milan noir'),
((SELECT id FROM bird WHERE name = 'MILAN_ROYAL'), (SELECT id FROM language WHERE name = 'FR'), 'Milan royal'),
((SELECT id FROM bird WHERE name = 'MOINEAU_CISALPIN'), (SELECT id FROM language WHERE name = 'FR'),
'Moineau cisalpin'),
((SELECT id FROM bird WHERE name = 'MOINEAU_DOMESTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Moineau domestique'),
((SELECT id FROM bird WHERE name = 'MOINEAU_ESPAGNOL'), (SELECT id FROM language WHERE name = 'FR'),
'Moineau espagnol'),
((SELECT id FROM bird WHERE name = 'MOINEAU_FRIQUET'), (SELECT id FROM language WHERE name = 'FR'),
'Moineau friquet'),
((SELECT id FROM bird WHERE name = 'MOINEAU_SOULCIE'), (SELECT id FROM language WHERE name = 'FR'),
'Moineau soulcie'),
((SELECT id FROM bird WHERE name = 'MONTICOLE_BLEU'), (SELECT id FROM language WHERE name = 'FR'),
'Monticole bleu'),
((SELECT id FROM bird WHERE name = 'MONTICOLE_DE_ROCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Monticole de roche'),
((SELECT id FROM bird WHERE name = 'MOUETTE_ATRICILLE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette atricille'),
((SELECT id FROM bird WHERE name = 'MOUETTE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette blanche'),
((SELECT id FROM bird WHERE name = 'MOUETTE_DE_FRANKLIN'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette de Franklin'),
((SELECT id FROM bird WHERE name = 'MOUETTE_DE_SABINE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette de Sabine'),
((SELECT id FROM bird WHERE name = 'MOUETTE_MELANOCEPHALE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette mélanocéphale'),
((SELECT id FROM bird WHERE name = 'MOUETTE_PYGMEE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette pygmée'),
((SELECT id FROM bird WHERE name = 'MOUETTE_RIEUSE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette rieuse'),
((SELECT id FROM bird WHERE name = 'MOUETTE_TRIDACTYLE'), (SELECT id FROM language WHERE name = 'FR'),
'Mouette tridactyle'),
((SELECT id FROM bird WHERE name = 'NETTE_ROUSSE'), (SELECT id FROM language WHERE name = 'FR'), 'Nette rousse'),
((SELECT id FROM bird WHERE name = 'NIVEROLLE_ALPINE'), (SELECT id FROM language WHERE name = 'FR'),
'Niverolle alpine'),
((SELECT id FROM bird WHERE name = 'OCEANITE_CULBLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Océanite culblanc'),
((SELECT id FROM bird WHERE name = 'OCEANITE_DE_CASTRO'), (SELECT id FROM language WHERE name = 'FR'),
'Océanite de Castro'),
((SELECT id FROM bird WHERE name = 'OCEANITE_TEMPETE'), (SELECT id FROM language WHERE name = 'FR'),
'Océanite tempête'),
((SELECT id FROM bird WHERE name = 'OEDICNEME_CRIARD'), (SELECT id FROM language WHERE name = 'FR'),
'Oedicnème criard'),
((SELECT id FROM bird WHERE name = 'OIE_A_BEC_COURT'), (SELECT id FROM language WHERE name = 'FR'),
'Oie à bec court'),
((SELECT id FROM bird WHERE name = 'OIE_CENDREE'), (SELECT id FROM language WHERE name = 'FR'), 'Oie cendrée'),
((SELECT id FROM bird WHERE name = 'OIE_DES_MOISSONS'), (SELECT id FROM language WHERE name = 'FR'),
'Oie des moissons'),
((SELECT id FROM bird WHERE name = 'OIE_DES_NEIGES'), (SELECT id FROM language WHERE name = 'FR'),
'Oie des neiges'),
((SELECT id FROM bird WHERE name = 'OIE_NAINE'), (SELECT id FROM language WHERE name = 'FR'), 'Oie naine'),
((SELECT id FROM bird WHERE name = 'OIE_RIEUSE'), (SELECT id FROM language WHERE name = 'FR'), 'Oie rieuse'),
((SELECT id FROM bird WHERE name = 'OUETTE_D_EGYPTE'), (SELECT id FROM language WHERE name = 'FR'),
'Ouette d''Égypte'),
((SELECT id FROM bird WHERE name = 'OUTARDE_BARBUE'), (SELECT id FROM language WHERE name = 'FR'),
'Outarde barbue'),
((SELECT id FROM bird WHERE name = 'OUTARDE_CANEPETIERE'), (SELECT id FROM language WHERE name = 'FR'),
'Outarde canepetière'),
((SELECT id FROM bird WHERE name = 'OUTARDE_DE_MACQUEEN'), (SELECT id FROM language WHERE name = 'FR'),
'Outarde de Macqueen'),
((SELECT id FROM bird WHERE name = 'OUTARDE_HOUBARA'), (SELECT id FROM language WHERE name = 'FR'),
'Outarde houbara'),
((SELECT id FROM bird WHERE name = 'PANURE_A_MOUSTACHES'), (SELECT id FROM language WHERE name = 'FR'),
'Panure à moustaches'),
((SELECT id FROM bird WHERE name = 'PELICAN_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Pélican blanc'),
((SELECT id FROM bird WHERE name = 'PELICAN_FRISE'), (SELECT id FROM language WHERE name = 'FR'),
'Pélican frisé'),
((SELECT id FROM bird WHERE name = 'PELICAN_GRIS'), (SELECT id FROM language WHERE name = 'FR'), 'Pélican gris'),
((SELECT id FROM bird WHERE name = 'PERDRIX_BARTAVELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Perdrix bartavelle'),
((SELECT id FROM bird WHERE name = 'PERDRIX_GRISE'), (SELECT id FROM language WHERE name = 'FR'),
'Perdrix grise'),
((SELECT id FROM bird WHERE name = 'PERDRIX_ROUGE'), (SELECT id FROM language WHERE name = 'FR'),
'Perdrix rouge'),
((SELECT id FROM bird WHERE name = 'PETIT_GRAVELOT'), (SELECT id FROM language WHERE name = 'FR'),
'Petit Gravelot'),
((SELECT id FROM bird WHERE name = 'PETIT_DUC_SCOPS'), (SELECT id FROM language WHERE name = 'FR'),
'Petit-duc scops'),
((SELECT id FROM bird WHERE name = 'PHALAROPE_A_BEC_ETROIT'), (SELECT id FROM language WHERE name = 'FR'),
'Phalarope à bec étroit'),
((SELECT id FROM bird WHERE name = 'PHALAROPE_A_BEC_LARGE'), (SELECT id FROM language WHERE name = 'FR'),
'Phalarope à bec large'),
((SELECT id FROM bird WHERE name = 'PHRAGMITE_AQUATIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Phragmite aquatique'),
((SELECT id FROM bird WHERE name = 'PHRAGMITE_DES_JONCS'), (SELECT id FROM language WHERE name = 'FR'),
'Phragmite des joncs'),
((SELECT id FROM bird WHERE name = 'PIC_A_DOS_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Pic à dos blanc'),
((SELECT id FROM bird WHERE name = 'PIC_CENDRE'), (SELECT id FROM language WHERE name = 'FR'), 'Pic cendré'),
((SELECT id FROM bird WHERE name = 'PIC_EPEICHE'), (SELECT id FROM language WHERE name = 'FR'), 'Pic épeiche'),
((SELECT id FROM bird WHERE name = 'PIC_EPEICHETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Pic épeichette'),
((SELECT id FROM bird WHERE name = 'PIC_MAR'), (SELECT id FROM language WHERE name = 'FR'), 'Pic mar'),
((SELECT id FROM bird WHERE name = 'PIC_NOIR'), (SELECT id FROM language WHERE name = 'FR'), 'Pic noir'),
((SELECT id FROM bird WHERE name = 'PIC_TRIDACTYLE'), (SELECT id FROM language WHERE name = 'FR'),
'Pic tridactyle'),
((SELECT id FROM bird WHERE name = 'PIC_VERT'), (SELECT id FROM language WHERE name = 'FR'), 'Pic vert'),
((SELECT id FROM bird WHERE name = 'PIE_BAVARDE'), (SELECT id FROM language WHERE name = 'FR'), 'Pie bavarde'),
((SELECT id FROM bird WHERE name = 'PIE_GRIECHE_A_POITRINE_ROSE'), (SELECT id FROM language WHERE name = 'FR'),
'Pie-grièche à poitrine rose'),
((SELECT id FROM bird WHERE name = 'PIE_GRIECHE_A_TETE_ROUSSE'), (SELECT id FROM language WHERE name = 'FR'),
'Pie-grièche à tête rousse'),
((SELECT id FROM bird WHERE name = 'PIE_GRIECHE_ECORCHEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Pie-grièche écorcheur'),
((SELECT id FROM bird WHERE name = 'PIE_GRIECHE_GRISE'), (SELECT id FROM language WHERE name = 'FR'),
'Pie-grièche grise'),
((SELECT id FROM bird WHERE name = 'PIE_GRIECHE_ISABELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Pie-grièche isabelle'),
((SELECT id FROM bird WHERE name = 'PIGEON_BISET_DOMESTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Pigeon biset'),
((SELECT id FROM bird WHERE name = 'PIGEON_COLOMBIN'), (SELECT id FROM language WHERE name = 'FR'),
'Pigeon colombin'),
((SELECT id FROM bird WHERE name = 'PIGEON_RAMIER'), (SELECT id FROM language WHERE name = 'FR'),
'Pigeon ramier'),
((SELECT id FROM bird WHERE name = 'PINSON_DES_ARBRES'), (SELECT id FROM language WHERE name = 'FR'),
'Pinson des arbres'),
((SELECT id FROM bird WHERE name = 'PINSON_DU_NORD'), (SELECT id FROM language WHERE name = 'FR'),
'Pinson du Nord'),
((SELECT id FROM bird WHERE name = 'PIPIT_A_DOS_OLIVE'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit à dos olive'),
((SELECT id FROM bird WHERE name = 'PIPIT_A_GORGE_ROUSSE'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit à gorge rousse'),
((SELECT id FROM bird WHERE name = 'PIPIT_DE_RICHARD'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit de Richard'),
((SELECT id FROM bird WHERE name = 'PIPIT_DES_ARBRES'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit des arbres'),
((SELECT id FROM bird WHERE name = 'PIPIT_FARLOUSE'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit farlouse'),
((SELECT id FROM bird WHERE name = 'PIPIT_ROUSSELINE'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit rousseline'),
((SELECT id FROM bird WHERE name = 'PIPIT_SPIONCELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Pipit spioncelle'),
((SELECT id FROM bird WHERE name = 'PLONGEON_A_BEC_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Plongeon à bec blanc'),
((SELECT id FROM bird WHERE name = 'PLONGEON_ARCTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Plongeon arctique'),
((SELECT id FROM bird WHERE name = 'PLONGEON_CATMARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Plongeon catmarin'),
((SELECT id FROM bird WHERE name = 'PLONGEON_DU_PACIFIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Plongeon du Pacifique'),
((SELECT id FROM bird WHERE name = 'PLONGEON_IMBRIN'), (SELECT id FROM language WHERE name = 'FR'),
'Plongeon imbrin'),
((SELECT id FROM bird WHERE name = 'PLUVIER_ARGENTE'), (SELECT id FROM language WHERE name = 'FR'),
'Pluvier argenté'),
((SELECT id FROM bird WHERE name = 'PLUVIER_DORE'), (SELECT id FROM language WHERE name = 'FR'), 'Pluvier doré'),
((SELECT id FROM bird WHERE name = 'PLUVIER_FAUVE'), (SELECT id FROM language WHERE name = 'FR'),
'Pluvier fauve'),
((SELECT id FROM bird WHERE name = 'PLUVIER_GUIGNARD'), (SELECT id FROM language WHERE name = 'FR'),
'Pluvier guignard'),
((SELECT id FROM bird WHERE name = 'POUILLOT_A_GRANDS_SOURCILS'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot à grands sourcils'),
((SELECT id FROM bird WHERE name = 'POUILLOT_BRUN'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot brun'),
((SELECT id FROM bird WHERE name = 'POUILLOT_DE_BONELLI'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot de Bonelli'),
((SELECT id FROM bird WHERE name = 'POUILLOT_DE_HUME'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot de Hume'),
((SELECT id FROM bird WHERE name = 'POUILLOT_DE_PALLAS'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot de Pallas'),
((SELECT id FROM bird WHERE name = 'POUILLOT_DE_SCHWARZ'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot de Schwarz'),
((SELECT id FROM bird WHERE name = 'POUILLOT_DE_SIBERIE'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot de Sibérie'),
((SELECT id FROM bird WHERE name = 'POUILLOT_FITIS'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot fitis'),
((SELECT id FROM bird WHERE name = 'POUILLOT_IBERIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot ibérique'),
((SELECT id FROM bird WHERE name = 'POUILLOT_SIFFLEUR'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot siffleur'),
((SELECT id FROM bird WHERE name = 'POUILLOT_VELOCE'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot véloce'),
((SELECT id FROM bird WHERE name = 'POUILLOT_VERDATRE'), (SELECT id FROM language WHERE name = 'FR'),
'Pouillot verdâtre'),
((SELECT id FROM bird WHERE name = 'PUFFIN_CENDRE'), (SELECT id FROM language WHERE name = 'FR'),
'Puffin boréal'),
((SELECT id FROM bird WHERE name = 'PUFFIN_DE_SCOPOLI'), (SELECT id FROM language WHERE name = 'FR'),
'Puffin de Scopoli'),
((SELECT id FROM bird WHERE name = 'PUFFIN_DES_ANGLAIS'), (SELECT id FROM language WHERE name = 'FR'),
'Puffin des Anglais'),
((SELECT id FROM bird WHERE name = 'PUFFIN_FULIGINEUX'), (SELECT id FROM language WHERE name = 'FR'),
'Puffin fuligineux'),
((SELECT id FROM bird WHERE name = 'PUFFIN_YELKOUAN'), (SELECT id FROM language WHERE name = 'FR'),
'Puffin yelkouan'),
((SELECT id FROM bird WHERE name = 'PYGARGUE_A_QUEUE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Pygargue à queue blanche'),
((SELECT id FROM bird WHERE name = 'RALE_D_EAU'), (SELECT id FROM language WHERE name = 'FR'), 'Râle d''eau'),
((SELECT id FROM bird WHERE name = 'RALE_DES_GENETS'), (SELECT id FROM language WHERE name = 'FR'),
'Râle des genêts'),
((SELECT id FROM bird WHERE name = 'REMIZ_PENDULINE'), (SELECT id FROM language WHERE name = 'FR'),
'Rémiz penduline'),
((SELECT id FROM bird WHERE name = 'ROITELET_A_TRIPLE_BANDEAU'), (SELECT id FROM language WHERE name = 'FR'),
'Roitelet triple-bandeau'),
((SELECT id FROM bird WHERE name = 'ROITELET_HUPPE'), (SELECT id FROM language WHERE name = 'FR'),
'Roitelet huppé'),
((SELECT id FROM bird WHERE name = 'ROLLIER_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Rollier d''Europe'),
((SELECT id FROM bird WHERE name = 'ROSELIN_CRAMOISI'), (SELECT id FROM language WHERE name = 'FR'),
'Roselin cramoisi'),
((SELECT id FROM bird WHERE name = 'ROSELIN_GITHAGINE'), (SELECT id FROM language WHERE name = 'FR'),
'Roselin githagine'),
((SELECT id FROM bird WHERE name = 'ROSSIGNOL_PHILOMELE'), (SELECT id FROM language WHERE name = 'FR'),
'Rossignol philomèle'),
((SELECT id FROM bird WHERE name = 'ROSSIGNOL_PROGNE'), (SELECT id FROM language WHERE name = 'FR'),
'Rossignol progné'),
((SELECT id FROM bird WHERE name = 'ROUGEGORGE_FAMILIER'), (SELECT id FROM language WHERE name = 'FR'),
'Rougegorge familier'),
((SELECT id FROM bird WHERE name = 'ROUGEQUEUE_A_FRONT_BLANC'), (SELECT id FROM language WHERE name = 'FR'),
'Rougequeue à front blanc'),
((SELECT id FROM bird WHERE name = 'ROUGEQUEUE_NOIR'), (SELECT id FROM language WHERE name = 'FR'),
'Rougequeue noir'),
((SELECT id FROM bird WHERE name = 'ROUSSEROLLE_DES_BUISSONS'), (SELECT id FROM language WHERE name = 'FR'),
'Rousserolle des buissons'),
((SELECT id FROM bird WHERE name = 'ROUSSEROLLE_EFFARVATTE'), (SELECT id FROM language WHERE name = 'FR'),
'Rousserolle effarvatte'),
((SELECT id FROM bird WHERE name = 'ROUSSEROLLE_ISABELLE'), (SELECT id FROM language WHERE name = 'FR'),
'Rousserolle isabelle'),
((SELECT id FROM bird WHERE name = 'ROUSSEROLLE_TURDOIDE'), (SELECT id FROM language WHERE name = 'FR'),
'Rousserolle turdoïde'),
((SELECT id FROM bird WHERE name = 'ROUSSEROLLE_VERDEROLLE'), (SELECT id FROM language WHERE name = 'FR'),
'Rousserolle verderolle'),
((SELECT id FROM bird WHERE name = 'SARCELLE_A_AILES_BLEUES'), (SELECT id FROM language WHERE name = 'FR'),
'Sarcelle à ailes bleues'),
((SELECT id FROM bird WHERE name = 'SARCELLE_D_ETE'), (SELECT id FROM language WHERE name = 'FR'),
'Sarcelle d''été'),
((SELECT id FROM bird WHERE name = 'SARCELLE_D_HIVER'), (SELECT id FROM language WHERE name = 'FR'),
'Sarcelle d''hiver'),
((SELECT id FROM bird WHERE name = 'SARCELLE_MARBREE'), (SELECT id FROM language WHERE name = 'FR'),
'Sarcelle marbrée'),
((SELECT id FROM bird WHERE name = 'SERIN_CINI'), (SELECT id FROM language WHERE name = 'FR'), 'Serin cini'),
((SELECT id FROM bird WHERE name = 'SITTELLE_TORCHEPOT'), (SELECT id FROM language WHERE name = 'FR'),
'Sittelle torchepot'),
((SELECT id FROM bird WHERE name = 'SIZERIN_FLAMME'), (SELECT id FROM language WHERE name = 'FR'),
'Sizerin flammé'),
((SELECT id FROM bird WHERE name = 'SPATULE_BLANCHE'), (SELECT id FROM language WHERE name = 'FR'),
'Spatule blanche'),
((SELECT id FROM bird WHERE name = 'STERNE_ARCTIQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne arctique'),
((SELECT id FROM bird WHERE name = 'STERNE_CASPIENNE'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne caspienne'),
((SELECT id FROM bird WHERE name = 'STERNE_CAUGEK'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne caugek'),
((SELECT id FROM bird WHERE name = 'STERNE_DE_DOUGALL'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne de Dougall'),
((SELECT id FROM bird WHERE name = 'STERNE_HANSEL'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne hansel'),
((SELECT id FROM bird WHERE name = 'STERNE_NAINE'), (SELECT id FROM language WHERE name = 'FR'), 'Sterne naine'),
((SELECT id FROM bird WHERE name = 'STERNE_PIERREGARIN'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne pierregarin'),
((SELECT id FROM bird WHERE name = 'STERNE_VOYAGEUSE'), (SELECT id FROM language WHERE name = 'FR'),
'Sterne voyageuse'),
((SELECT id FROM bird WHERE name = 'SYRRHAPTE_PARADOXAL'), (SELECT id FROM language WHERE name = 'FR'),
'Syrrhapte paradoxal'),
((SELECT id FROM bird WHERE name = 'TADORNE_CASARCA'), (SELECT id FROM language WHERE name = 'FR'),
'Tadorne casarca'),
((SELECT id FROM bird WHERE name = 'TADORNE_DE_BELON'), (SELECT id FROM language WHERE name = 'FR'),
'Tadorne de Belon'),
((SELECT id FROM bird WHERE name = 'TALEVE_SULTANE'), (SELECT id FROM language WHERE name = 'FR'),
'Talève sultane'),
((SELECT id FROM bird WHERE name = 'TALEVE_VIOLACEE'), (SELECT id FROM language WHERE name = 'FR'),
'Talève violacée'),
((SELECT id FROM bird WHERE name = 'TARIER_DES_PRES'), (SELECT id FROM language WHERE name = 'FR'),
'Tarier des prés'),
((SELECT id FROM bird WHERE name = 'TARIER_PATRE'), (SELECT id FROM language WHERE name = 'FR'), 'Tarier pâtre'),
((SELECT id FROM bird WHERE name = 'TARIN_DES_AULNES'), (SELECT id FROM language WHERE name = 'FR'),
'Tarin des aulnes'),
((SELECT id FROM bird WHERE name = 'TETRAS_LYRE'), (SELECT id FROM language WHERE name = 'FR'), 'Tétras lyre'),
((SELECT id FROM bird WHERE name = 'TICHODROME_ECHELETTE'), (SELECT id FROM language WHERE name = 'FR'),
'Tichodrome échelette'),
((SELECT id FROM bird WHERE name = 'TORCOL_FOURMILIER'), (SELECT id FROM language WHERE name = 'FR'),
'Torcol fourmilier'),
((SELECT id FROM bird WHERE name = 'TOURNEPIERRE_A_COLLIER'), (SELECT id FROM language WHERE name = 'FR'),
'Tournepierre à collier'),
((SELECT id FROM bird WHERE name = 'TOURTERELLE_DES_BOIS'), (SELECT id FROM language WHERE name = 'FR'),
'Tourterelle des bois'),
((SELECT id FROM bird WHERE name = 'TOURTERELLE_TURQUE'), (SELECT id FROM language WHERE name = 'FR'),
'Tourterelle turque'),
((SELECT id FROM bird WHERE name = 'TRAQUET_DU_DESERT'), (SELECT id FROM language WHERE name = 'FR'),
'Traquet du désert'),
((SELECT id FROM bird WHERE name = 'TRAQUET_MOTTEUX'), (SELECT id FROM language WHERE name = 'FR'),
'Traquet motteux'),
((SELECT id FROM bird WHERE name = 'TRAQUET_OREILLARD'), (SELECT id FROM language WHERE name = 'FR'),
'Traquet oreillard'),
((SELECT id FROM bird WHERE name = 'TROGLODYTE_MIGNON'), (SELECT id FROM language WHERE name = 'FR'),
'Troglodyte mignon'),
((SELECT id FROM bird WHERE name = 'VANNEAU_HUPPE'), (SELECT id FROM language WHERE name = 'FR'),
'Vanneau huppé'),
((SELECT id FROM bird WHERE name = 'VANNEAU_SOCIABLE'), (SELECT id FROM language WHERE name = 'FR'),
'Vanneau sociable'),
((SELECT id FROM bird WHERE name = 'VAUTOUR_FAUVE'), (SELECT id FROM language WHERE name = 'FR'),
'Vautour fauve'),
((SELECT id FROM bird WHERE name = 'VAUTOUR_MOINE'), (SELECT id FROM language WHERE name = 'FR'),
'Vautour moine'),
((SELECT id FROM bird WHERE name = 'VAUTOUR_PERCNOPTERE'), (SELECT id FROM language WHERE name = 'FR'),
'Percnoptère d''Égypte'),
((SELECT id FROM bird WHERE name = 'VENTURON_MONTAGNARD'), (SELECT id FROM language WHERE name = 'FR'),
'Venturon montagnard'),
((SELECT id FROM bird WHERE name = 'VERDIER_D_EUROPE'), (SELECT id FROM language WHERE name = 'FR'),
'Verdier d''Europe'),
((SELECT id FROM bird WHERE name = 'MESANGE_DES_SAULES'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange des saules'),
((SELECT id FROM bird WHERE name = 'MESANGE_ALPESTRE'), (SELECT id FROM language WHERE name = 'FR'),
'Mésange alpestre');
INSERT INTO picture_type_translation(picture_type_id, language_id, translation)
VALUES ((SELECT id FROM picture_type WHERE name = 'ADULT'), (SELECT id FROM language WHERE name = 'FR'), 'Adulte'),
((SELECT id FROM picture_type WHERE name = 'ADULT_FEMALE'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte femelle'),
((SELECT id FROM picture_type WHERE name = 'ADULT_INTERNUPTIAL'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte (plumage internuptial)'),
((SELECT id FROM picture_type WHERE name = 'ADULT_INTERNUPTIAL_FEMALE'),
(SELECT id FROM language WHERE name = 'FR'), 'Adulte femelle (plumage internuptial)'),
((SELECT id FROM picture_type WHERE name = 'ADULT_INTERNUPTIAL_MALE'),
(SELECT id FROM language WHERE name = 'FR'), 'Adulte mâle (plumage internuptial)'),
((SELECT id FROM picture_type WHERE name = 'ADULT_MALE'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte mâle'),
((SELECT id FROM picture_type WHERE name = 'ADULT_NUPTIAL'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte (plumage nuptial)'),
((SELECT id FROM picture_type WHERE name = 'ADULT_NUPTIAL_FEMALE'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte femelle (plumage nuptial)'),
((SELECT id FROM picture_type WHERE name = 'ADULT_NUPTIAL_MALE'), (SELECT id FROM language WHERE name = 'FR'),
'Adulte mâle (plumage nuptial)'),
((SELECT id FROM picture_type WHERE name = 'DARK_MORPH'), (SELECT id FROM language WHERE name = 'FR'),
'Forme sombre'),
((SELECT id FROM picture_type WHERE name = 'JUVENILE'), (SELECT id FROM language WHERE name = 'FR'), 'Juvénile'),
((SELECT id FROM picture_type WHERE name = 'JUVENILE_FEMALE'), (SELECT id FROM language WHERE name = 'FR'),
'Juvénile femelle'),
((SELECT id FROM picture_type WHERE name = 'JUVENILE_MALE'), (SELECT id FROM language WHERE name = 'FR'),
'Juvénile mâle'),
((SELECT id FROM picture_type WHERE name = 'LIGHT_MORPH'), (SELECT id FROM language WHERE name = 'FR'),
'Forme claire'),
((SELECT id FROM picture_type WHERE name = 'SUB_SPECIES'), (SELECT id FROM language WHERE name = 'FR'),
'Sous-espèce'),
((SELECT id FROM picture_type WHERE name = 'UNKNOWN'), (SELECT id FROM language WHERE name = 'FR'), 'Inconnu');
INSERT INTO sound_type_translation(sound_type_id, language_id, translation)
VALUES ((SELECT id FROM sound_type WHERE name = 'ALARM'), (SELECT id FROM language WHERE name = 'FR'), 'Alarme'),
((SELECT id FROM sound_type WHERE name = 'CALL'), (SELECT id FROM language WHERE name = 'FR'), 'Cri'),
((SELECT id FROM sound_type WHERE name = 'FLY_CALL'), (SELECT id FROM language WHERE name = 'FR'), 'Cri de vol'),
((SELECT id FROM sound_type WHERE name = 'JUVENILE_CALL'), (SELECT id FROM language WHERE name = 'FR'),
'Cri de juvénile'),
((SELECT id FROM sound_type WHERE name = 'SONG'), (SELECT id FROM language WHERE name = 'FR'), 'Chant'),
((SELECT id FROM sound_type WHERE name = 'UNKNOWN'), (SELECT id FROM language WHERE name = 'FR'), 'Inconnu');
INSERT INTO question_type_translation(question_type_id, language_id, translation)
VALUES ((SELECT id FROM question_type WHERE name = 'PICTURE_EXACT'), (SELECT id FROM language WHERE name = 'FR'),
'Image'),
((SELECT id FROM question_type WHERE name = 'PICTURE_MULTICHOICE'), (SELECT id FROM language WHERE name = 'FR'),
'Image (choix multiples)'),
((SELECT id FROM question_type WHERE name = 'SOUND_EXACT'), (SELECT id FROM language WHERE name = 'FR'), 'Son'),
((SELECT id FROM question_type WHERE name = 'SOUND_MULTICHOICE'), (SELECT id FROM language WHERE name = 'FR'),
'Son (choix multiples)'),
((SELECT id FROM question_type WHERE name = 'SOUND_MULTICHOICE_PICTURE'),
(SELECT id FROM language WHERE name = 'FR'), 'Son (choix multiple d''images)');
INSERT INTO migration_type_translation(migration_type_id, language_id, translation)
VALUES ((SELECT id FROM migration_type WHERE name = 'MIGRATION_COURTE_PARTIELLE'),
(SELECT id FROM language WHERE name = 'FR'), 'Migration courte (partielle)'),
((SELECT id FROM migration_type WHERE name = 'MIGRATION_LONGUE_PARTIELLE'),
(SELECT id FROM language WHERE name = 'FR'), 'Migration longue (partielle)'),
((SELECT id FROM migration_type WHERE name = 'MIGRATION_COURTE'), (SELECT id FROM language WHERE name = 'FR'),
'Migration courte'),
((SELECT id FROM migration_type WHERE name = 'MIGRATION_LONGUE'), (SELECT id FROM language WHERE name = 'FR'),
'Migration longue'),
((SELECT id FROM migration_type WHERE name = 'SEDENTAIRE'), (SELECT id FROM language WHERE name = 'FR'),
'Sédentaire'),
((SELECT id FROM migration_type WHERE name = 'UNKNOWN'), (SELECT id FROM language WHERE name = 'FR'), 'Inconnu');
@@ -0,0 +1,177 @@
DROP TABLE IF EXISTS language CASCADE;
CREATE TABLE language
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS family CASCADE;
CREATE TABLE family
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS family_translation CASCADE;
CREATE TABLE family_translation
(
family_id smallint NOT NULL REFERENCES family (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (family_id, language_id)
);
DROP TABLE IF EXISTS migration_type CASCADE;
CREATE TABLE migration_type
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS migration_type_translation CASCADE;
CREATE TABLE migration_type_translation
(
migration_type_id smallint NOT NULL REFERENCES migration_type (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (migration_type_id, language_id)
);
DROP TABLE IF EXISTS bird CASCADE;
CREATE TABLE bird
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
family_id smallint NOT NULL REFERENCES family (id) ON DELETE RESTRICT,
migration_type_id smallint NOT NULL REFERENCES migration_type (id) ON DELETE RESTRICT,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS bird_translation CASCADE;
CREATE TABLE bird_translation
(
bird_id smallint NOT NULL REFERENCES bird (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (bird_id, language_id)
);
DROP TABLE IF EXISTS fetcher CASCADE;
CREATE TABLE fetcher
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS profile CASCADE;
CREATE TABLE profile
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS picture_type CASCADE;
CREATE TABLE picture_type
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS picture_type_translation CASCADE;
CREATE TABLE picture_type_translation
(
picture_type_id smallint NOT NULL REFERENCES picture_type (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (picture_type_id, language_id)
);
DROP TABLE IF EXISTS picture CASCADE;
CREATE TABLE picture
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
source varchar NOT NULL,
file_name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS sound_type CASCADE;
CREATE TABLE sound_type
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS sound_type_translation CASCADE;
CREATE TABLE sound_type_translation
(
sound_type_id smallint NOT NULL REFERENCES sound_type (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (sound_type_id, language_id)
);
DROP TABLE IF EXISTS sound CASCADE;
CREATE TABLE sound
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
source varchar NOT NULL,
file_name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS question_type CASCADE;
CREATE TABLE question_type
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL UNIQUE
);
DROP TABLE IF EXISTS question_type_translation CASCADE;
CREATE TABLE question_type_translation
(
question_type_id smallint NOT NULL REFERENCES question_type (id) ON DELETE CASCADE,
language_id smallint NOT NULL REFERENCES language (id) ON DELETE CASCADE,
translation varchar NOT NULL,
PRIMARY KEY (question_type_id, language_id)
);
DROP TABLE IF EXISTS bird_parameters CASCADE;
CREATE TABLE bird_parameters
(
id smallint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
profile_id smallint NOT NULL REFERENCES profile (id) ON DELETE CASCADE,
bird_id smallint NOT NULL REFERENCES bird (id) ON DELETE CASCADE,
enabled boolean NOT NULL DEFAULT true,
UNIQUE (profile_id, bird_id)
);
DROP TABLE IF EXISTS bird_parameters_picture_type CASCADE;
CREATE TABLE bird_parameters_picture_type
(
bird_parameters_id smallint NOT NULL REFERENCES bird_parameters (id) ON DELETE CASCADE,
picture_type_id smallint NOT NULL REFERENCES picture_type (id) ON DELETE CASCADE,
PRIMARY KEY (bird_parameters_id, picture_type_id)
);
DROP TABLE IF EXISTS bird_parameters_sound_type CASCADE;
CREATE TABLE bird_parameters_sound_type
(
bird_parameters_id smallint NOT NULL REFERENCES bird_parameters (id) ON DELETE CASCADE,
sound_type_id smallint NOT NULL REFERENCES sound_type (id) ON DELETE CASCADE,
PRIMARY KEY (bird_parameters_id, sound_type_id)
);
DROP TABLE IF EXISTS bird_parameters_fetcher CASCADE;
CREATE TABLE bird_parameters_fetcher
(
bird_parameters_id smallint NOT NULL REFERENCES bird_parameters (id) ON DELETE CASCADE,
fetcher_id smallint NOT NULL REFERENCES fetcher (id) ON DELETE CASCADE,
PRIMARY KEY (bird_parameters_id, fetcher_id)
);
DROP TABLE IF EXISTS parameters CASCADE;
CREATE TABLE parameters
(
profile_id smallint NOT NULL REFERENCES profile (id) ON DELETE CASCADE,
max_guesses smallint NOT NULL DEFAULT 1,
questions_count smallint NOT NULL DEFAULT 20,
suggestions_count smallint NOT NULL DEFAULT 4
);
@@ -1,7 +1,26 @@
package ch.gtache.fro.gui; package ch.gtache.fro.gui;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import java.util.List;
/** /**
* Model for the settings view * Model for the settings view
*/ */
public interface SettingsModel extends Model { public interface SettingsModel extends Model {
/**
* Returns the bird practice parameters
*
* @return The parameters
*/
List<BirdPracticeParameters> birdPracticeParameters();
/**
* Returns the consolidated configuration
*
* @return The configuration
*/
GroupedBirdPracticeParameters configuration();
} }
@@ -1,7 +1,9 @@
package ch.gtache.fro.practice.gui; package ch.gtache.fro.practice.gui;
import ch.gtache.fro.gui.Model; import ch.gtache.fro.gui.Model;
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.PracticeParameters; import ch.gtache.fro.practice.PracticeParameters;
import ch.gtache.fro.practice.PracticeProfile;
import ch.gtache.fro.practice.QuestionType; import ch.gtache.fro.practice.QuestionType;
import java.util.List; import java.util.List;
@@ -11,6 +13,34 @@ import java.util.List;
*/ */
public interface PracticeSettingsModel extends Model { public interface PracticeSettingsModel extends Model {
/**
* Returns the available profiles
*
* @return The profiles
*/
List<PracticeProfile> availableProfiles();
/**
* Returns the selected profile
*
* @return The profile
*/
PracticeProfile profile();
/**
* Sets the profile
*
* @param profile The profile
*/
void setProfile(PracticeProfile profile);
/**
* Returns the bird practice parameters
*
* @return The parameters
*/
GroupedBirdPracticeParameters birdPracticeParameters();
/** /**
* Returns the list of practice types * Returns the list of practice types
* *
@@ -1,4 +1,5 @@
practice.settings.guesses.number.label=Number of available guesses practice.settings.guesses.number.label=Number of available guesses
practice.settings.profile.label=Profile
practice.settings.questions.number.label=Number of questions practice.settings.questions.number.label=Number of questions
practice.settings.start.button.label=Start practice.settings.start.button.label=Start
practice.settings.suggestions.number.label=Number of suggestions practice.settings.suggestions.number.label=Number of suggestions
@@ -1,4 +1,5 @@
practice.settings.guesses.number.label=Number of available guesses practice.settings.guesses.number.label=Number of available guesses
practice.settings.profile.label=Profile
practice.settings.questions.number.label=Number of questions practice.settings.questions.number.label=Number of questions
practice.settings.start.button.label=Start practice.settings.start.button.label=Start
practice.settings.suggestions.number.label=Number of suggestions practice.settings.suggestions.number.label=Number of suggestions
@@ -1,4 +1,5 @@
practice.settings.guesses.number.label=Nombre d'essais disponibles practice.settings.guesses.number.label=Nombre d'essais disponibles
practice.settings.profile.label=Profil
practice.settings.questions.number.label=Nombre de questions practice.settings.questions.number.label=Nombre de questions
practice.settings.start.button.label=Démarrer practice.settings.start.button.label=Démarrer
practice.settings.suggestions.number.label=Nombre de suggestions practice.settings.suggestions.number.label=Nombre de suggestions
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>gui-fx</artifactId> <artifactId>gui-fx</artifactId>
<properties> <properties>
<javafx.version>24.0.2</javafx.version> <javafx.version>25</javafx.version>
<controlsfx.version>11.2.2</controlsfx.version> <controlsfx.version>11.2.2</controlsfx.version>
</properties> </properties>
@@ -5,6 +5,7 @@ import ch.gtache.fro.practice.BirdPracticeParameters;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Singleton; import jakarta.inject.Singleton;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
import java.util.Objects; import java.util.Objects;
@@ -19,12 +20,27 @@ public final class FXSettingsController implements SettingsController {
@FXML @FXML
private TableView<BirdPracticeParameters> table; private TableView<BirdPracticeParameters> table;
@FXML
private TableColumn<BirdPracticeParameters, Boolean> enabledColumn;
@FXML
private TableColumn<BirdPracticeParameters, String> birdColumn;
@FXML
private TableColumn fetchersColumn;
@FXML
private TableColumn picturesColumn;
@FXML
private TableColumn soundsColumn;
@Inject @Inject
FXSettingsController(final FXSettingsModel model) { FXSettingsController(final FXSettingsModel model) {
this.model = Objects.requireNonNull(model); this.model = Objects.requireNonNull(model);
} }
@FXML
private void initialize() {
table.setItems(model.birdPracticeParameters());
}
@Override @Override
public void importSettings() { public void importSettings() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@@ -2,6 +2,9 @@ package ch.gtache.fro.gui.fx;
import ch.gtache.fro.gui.SettingsModel; import ch.gtache.fro.gui.SettingsModel;
import ch.gtache.fro.practice.BirdPracticeParameters; import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
import ch.gtache.fro.practice.PracticeProfileProvider;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Singleton; import jakarta.inject.Singleton;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@@ -16,7 +19,18 @@ public final class FXSettingsModel implements SettingsModel {
private final ObservableList<BirdPracticeParameters> birdParameters; private final ObservableList<BirdPracticeParameters> birdParameters;
@Inject @Inject
FXSettingsModel() { FXSettingsModel(final PracticeProfileProvider profileProvider,
final GroupedBirdPracticeParametersManager birdPracticeParametersManager) {
this.birdParameters = FXCollections.observableArrayList(); this.birdParameters = FXCollections.observableArrayList();
} }
@Override
public ObservableList<BirdPracticeParameters> birdPracticeParameters() {
return birdParameters;
}
@Override
public GroupedBirdPracticeParameters configuration() {
return null;
}
} }
@@ -1,5 +1,6 @@
package ch.gtache.fro.practice.gui.fx; package ch.gtache.fro.practice.gui.fx;
import ch.gtache.fro.practice.PracticeProfile;
import ch.gtache.fro.practice.PracticeRunner; import ch.gtache.fro.practice.PracticeRunner;
import ch.gtache.fro.practice.QuestionType; import ch.gtache.fro.practice.QuestionType;
import ch.gtache.fro.practice.gui.PracticeSettingsController; import ch.gtache.fro.practice.gui.PracticeSettingsController;
@@ -23,6 +24,9 @@ public final class FXPracticeSettingsController implements PracticeSettingsContr
private final FXPracticeSettingsModel model; private final FXPracticeSettingsModel model;
private final QuestionTypeConverter questionTypeConverter; private final QuestionTypeConverter questionTypeConverter;
private final PracticeRunner runner; private final PracticeRunner runner;
@FXML
private PrefixSelectionComboBox<PracticeProfile> profileCombobox;
@FXML @FXML
private PrefixSelectionComboBox<QuestionType> questionTypeCombobox; private PrefixSelectionComboBox<QuestionType> questionTypeCombobox;
@FXML @FXML
@@ -51,6 +55,9 @@ public final class FXPracticeSettingsController implements PracticeSettingsContr
@FXML @FXML
private void initialize() { private void initialize() {
profileCombobox.setItems(model.availableProfiles());
profileCombobox.valueProperty().bindBidirectional(model.profileProperty());
profileCombobox.setConverter(new PracticeProfileConverter());
questionTypeCombobox.setItems(model.questionTypes()); questionTypeCombobox.setItems(model.questionTypes());
questionTypeCombobox.valueProperty().bindBidirectional(model.questionTypeProperty()); questionTypeCombobox.valueProperty().bindBidirectional(model.questionTypeProperty());
questionTypeCombobox.setConverter(questionTypeConverter); questionTypeCombobox.setConverter(questionTypeConverter);
@@ -1,7 +1,10 @@
package ch.gtache.fro.practice.gui.fx; package ch.gtache.fro.practice.gui.fx;
import ch.gtache.fro.practice.PracticeConfiguration; import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
import ch.gtache.fro.practice.PracticeParameters; import ch.gtache.fro.practice.PracticeParameters;
import ch.gtache.fro.practice.PracticeProfile;
import ch.gtache.fro.practice.PracticeProfileProvider;
import ch.gtache.fro.practice.PracticeRun; import ch.gtache.fro.practice.PracticeRun;
import ch.gtache.fro.practice.QuestionType; import ch.gtache.fro.practice.QuestionType;
import ch.gtache.fro.practice.gui.PracticeSettingsModel; import ch.gtache.fro.practice.gui.PracticeSettingsModel;
@@ -28,9 +31,13 @@ import java.util.Map;
@Singleton @Singleton
public final class FXPracticeSettingsModel implements PracticeSettingsModel { public final class FXPracticeSettingsModel implements PracticeSettingsModel {
private static final int DEFAULT_GUESSES_NUMBER = 1;
private static final int DEFAULT_QUESTIONS_NUMBER = 20; private static final int DEFAULT_QUESTIONS_NUMBER = 20;
private static final int DEFAULT_SUGGESTIONS_NUMBER = 4; private static final int DEFAULT_SUGGESTIONS_NUMBER = 4;
private final ObservableList<PracticeProfile> availableProfiles;
private final ObjectProperty<PracticeProfile> profile;
private final ReadOnlyObjectWrapper<GroupedBirdPracticeParameters> birdPracticeParameters;
private final ObservableList<QuestionType> questionTypes; private final ObservableList<QuestionType> questionTypes;
private final ObjectProperty<QuestionType> questionType; private final ObjectProperty<QuestionType> questionType;
private final ReadOnlyBooleanWrapper hasSuggestions; private final ReadOnlyBooleanWrapper hasSuggestions;
@@ -41,19 +48,51 @@ public final class FXPracticeSettingsModel implements PracticeSettingsModel {
private final ObjectProperty<PracticeRun> practiceRun; private final ObjectProperty<PracticeRun> practiceRun;
@Inject @Inject
FXPracticeSettingsModel(final PracticeConfiguration configuration) { FXPracticeSettingsModel(final PracticeProfileProvider profileProvider,
final GroupedBirdPracticeParametersManager birdParametersManager) {
this.availableProfiles = FXCollections.observableArrayList(profileProvider.getAllObjectsAsync().join());
this.profile = new SimpleObjectProperty<>(availableProfiles.getFirst());
this.birdPracticeParameters = new ReadOnlyObjectWrapper<>(birdParametersManager.getObjectAsync(profile()).join());
this.questionTypes = FXCollections.observableArrayList(QuestionType.values()); this.questionTypes = FXCollections.observableArrayList(QuestionType.values());
this.questionType = new SimpleObjectProperty<>(QuestionType.PICTURE_EXACT); this.questionType = new SimpleObjectProperty<>(QuestionType.PICTURE_EXACT);
this.hasSuggestions = new ReadOnlyBooleanWrapper(true); this.hasSuggestions = new ReadOnlyBooleanWrapper(true);
this.guessesNumber = new SimpleIntegerProperty(configuration.guessesNumber()); this.guessesNumber = new SimpleIntegerProperty(DEFAULT_GUESSES_NUMBER);
this.questionsNumber = new SimpleIntegerProperty(DEFAULT_QUESTIONS_NUMBER); this.questionsNumber = new SimpleIntegerProperty(DEFAULT_QUESTIONS_NUMBER);
this.suggestionsNumber = new SimpleIntegerProperty(DEFAULT_SUGGESTIONS_NUMBER); this.suggestionsNumber = new SimpleIntegerProperty(DEFAULT_SUGGESTIONS_NUMBER);
this.practiceParameters = new ReadOnlyObjectWrapper<>(); this.practiceParameters = new ReadOnlyObjectWrapper<>();
this.practiceRun = new SimpleObjectProperty<>(); this.practiceRun = new SimpleObjectProperty<>();
practiceParameters.bind(Bindings.createObjectBinding(() -> new PracticeParametersImpl(configuration.birdPracticeParameters(), Map.of(questionType(), 1.0), birdPracticeParameters.bind(Bindings.createObjectBinding(() -> birdParametersManager.getObjectAsync(profile()).join(), profile));
guessesNumber(), questionsNumber(), suggestionsNumber()), questionType, guessesNumber, questionsNumber, suggestionsNumber)); practiceParameters.bind(Bindings.createObjectBinding(() -> new PracticeParametersImpl(birdPracticeParameters(), Map.of(questionType(), 1.0),
guessesNumber(), questionsNumber(), suggestionsNumber()), birdPracticeParameters, questionType, guessesNumber, questionsNumber, suggestionsNumber));
hasSuggestions.bind(questionType.isNotEqualTo(QuestionType.PICTURE_EXACT).and(questionType.isNotEqualTo(QuestionType.SOUND_EXACT))); hasSuggestions.bind(questionType.isNotEqualTo(QuestionType.PICTURE_EXACT).and(questionType.isNotEqualTo(QuestionType.SOUND_EXACT)));
guessesNumber.addListener((_, _, newValue) -> configuration.setGuessesNumber(newValue.intValue())); }
@Override
public ObservableList<PracticeProfile> availableProfiles() {
return availableProfiles;
}
@Override
public PracticeProfile profile() {
return profile.get();
}
@Override
public void setProfile(final PracticeProfile profile) {
this.profile.set(profile);
}
ObjectProperty<PracticeProfile> profileProperty() {
return profile;
}
@Override
public GroupedBirdPracticeParameters birdPracticeParameters() {
return birdPracticeParameters.get();
}
ReadOnlyObjectProperty<GroupedBirdPracticeParameters> birdPracticeParametersProperty() {
return birdPracticeParameters.getReadOnlyProperty();
} }
@Override @Override
@@ -0,0 +1,25 @@
package ch.gtache.fro.practice.gui.fx;
import ch.gtache.fro.practice.PracticeProfile;
import jakarta.inject.Inject;
import javafx.util.StringConverter;
/**
* {@link StringConverter} for {@link PracticeProfile}
*/
public class PracticeProfileConverter extends StringConverter<PracticeProfile> {
@Inject
PracticeProfileConverter() {
}
@Override
public String toString(final PracticeProfile object) {
return object.name();
}
@Override
public PracticeProfile fromString(final String string) {
return null;
}
}
@@ -8,6 +8,9 @@ import javafx.util.StringConverter;
import java.util.Objects; import java.util.Objects;
/**
* {@link StringConverter} for {@link QuestionType}
*/
public class QuestionTypeConverter extends StringConverter<QuestionType> { public class QuestionTypeConverter extends StringConverter<QuestionType> {
private final QuestionTypeTranslator translator; private final QuestionTypeTranslator translator;
@@ -5,7 +5,7 @@ import ch.gtache.fro.BirdProvider;
import ch.gtache.fro.BirdTranslator; import ch.gtache.fro.BirdTranslator;
import ch.gtache.fro.ProvisionException; import ch.gtache.fro.ProvisionException;
import ch.gtache.fro.TranslationException; import ch.gtache.fro.TranslationException;
import ch.gtache.fro.impl.BirdImpl; import ch.gtache.fro.impl.MinimalBirdImpl;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Singleton; import jakarta.inject.Singleton;
@@ -42,7 +42,7 @@ public class UserInputNormalizer {
Bird getBird(final String input) { Bird getBird(final String input) {
final var normalized = normalize(input); final var normalized = normalize(input);
return birdMap.getOrDefault(normalized, new BirdImpl(input)); return birdMap.getOrDefault(normalized, new MinimalBirdImpl(input));
} }
private static String normalize(final CharSequence input) { private static String normalize(final CharSequence input) {
@@ -12,15 +12,15 @@
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"> AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
<columns> <columns>
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0" <TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
text="%settings.table.column.enabled"/> text="%settings.table.column.bird" fx:id="birdColumn"/>
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0" <TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
text="%settings.table.column.bird"/> text="%settings.table.column.enabled" fx:id="enabledColumn"/>
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0" <TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
text="%settings.table.column.fetchers"/> text="%settings.table.column.fetchers" fx:id="fetchersColumn"/>
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0" <TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
text="%settings.table.column.pictures"/> text="%settings.table.column.pictures" fx:id="picturesColumn"/>
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0" <TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
text="%settings.table.column.sounds"/> text="%settings.table.column.sounds" fx:id="soundsColumn"/>
</columns> </columns>
<columnResizePolicy> <columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/> <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
@@ -4,36 +4,38 @@
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.*?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.PrefixSelectionComboBox?> <?import org.controlsfx.control.PrefixSelectionComboBox?>
<?import org.controlsfx.control.textfield.CustomTextField?> <?import org.controlsfx.control.textfield.CustomTextField?>
<GridPane hgap="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" vgap="10.0"
<GridPane hgap="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" vgap="10.0" xmlns="http://javafx.com/javafx/24.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticePictureExactController"> xmlns="http://javafx.com/javafx/24.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticePictureExactController">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="ALWAYS" /> <ColumnConstraints hgrow="ALWAYS"/>
<ColumnConstraints hgrow="SOMETIMES" /> <ColumnConstraints hgrow="SOMETIMES"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints vgrow="ALWAYS" /> <RowConstraints vgrow="ALWAYS"/>
<RowConstraints vgrow="ALWAYS" /> <RowConstraints vgrow="ALWAYS"/>
<RowConstraints vgrow="ALWAYS" /> <RowConstraints vgrow="ALWAYS"/>
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<ImageView fx:id="pictureView" fitHeight="800.0" fitWidth="800.0" pickOnBounds="true" preserveRatio="true" GridPane.columnSpan="2147483647" GridPane.rowIndex="1" /> <ImageView fx:id="pictureView" fitHeight="800.0" fitWidth="800.0" pickOnBounds="true" preserveRatio="true"
<CustomTextField fx:id="inputField" onAction="#enterPressed" GridPane.rowIndex="3" /> GridPane.columnSpan="2147483647" GridPane.rowIndex="1"/>
<PrefixSelectionComboBox fx:id="typeCombobox" managed="false" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <CustomTextField fx:id="inputField" onAction="#enterPressed" GridPane.rowIndex="3"/>
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed" text="%practice.picture.exact.validate.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="5" /> <PrefixSelectionComboBox fx:id="typeCombobox" managed="false" visible="false" GridPane.columnIndex="1"
<Label fx:id="progressLabel" text="Label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" /> GridPane.rowIndex="3"/>
<VBox fx:id="guessesBox" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4" /> <Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed"
<Label fx:id="answerLabel" GridPane.rowIndex="2" /> text="%practice.picture.exact.validate.button.label" GridPane.columnSpan="2147483647"
GridPane.halignment="CENTER" GridPane.rowIndex="5"/>
<Label fx:id="progressLabel" text="Label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"/>
<VBox fx:id="guessesBox" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4"/>
<Label fx:id="answerLabel" GridPane.rowIndex="2" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"/>
</children> </children>
<padding> <padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding> </padding>
</GridPane> </GridPane>
@@ -15,6 +15,7 @@
<ColumnConstraints hgrow="SOMETIMES" /> <ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES" />
@@ -22,15 +23,17 @@
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="%practice.settings.type.label" /> <Label text="%practice.settings.type.label" GridPane.rowIndex="1" />
<PrefixSelectionComboBox fx:id="questionTypeCombobox" GridPane.columnIndex="1" /> <PrefixSelectionComboBox fx:id="questionTypeCombobox" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label fx:id="suggestionsNumberLabel" text="%practice.settings.suggestions.number.label" GridPane.rowIndex="3" /> <Label fx:id="suggestionsNumberLabel" text="%practice.settings.suggestions.number.label" GridPane.rowIndex="4" />
<Spinner fx:id="suggestionsNumberSpinner" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <Spinner fx:id="suggestionsNumberSpinner" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Button mnemonicParsing="false" onAction="#startPressed" text="%practice.settings.start.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4" /> <Button mnemonicParsing="false" onAction="#startPressed" text="%practice.settings.start.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="5" />
<Label text="%practice.settings.questions.number.label" GridPane.rowIndex="1" /> <Label text="%practice.settings.questions.number.label" GridPane.rowIndex="2" />
<Spinner fx:id="questionsNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Spinner fx:id="questionsNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="%practice.settings.guesses.number.label" GridPane.rowIndex="2" /> <Label text="%practice.settings.guesses.number.label" GridPane.rowIndex="3" />
<Spinner fx:id="guessesNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <Spinner fx:id="guessesNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="%practice.settings.profile.label" />
<PrefixSelectionComboBox fx:id="profileCombobox" GridPane.columnIndex="1" />
</children> </children>
<padding> <padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
+4
View File
@@ -24,6 +24,10 @@
<groupId>ch.gtache.fro</groupId> <groupId>ch.gtache.fro</groupId>
<artifactId>fro-oiseaux-net</artifactId> <artifactId>fro-oiseaux-net</artifactId>
</dependency> </dependency>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-h2</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
@@ -1,5 +1,6 @@
package ch.gtache.fro.gui.run; package ch.gtache.fro.gui.run;
import ch.gtache.fro.Initializer;
import ch.gtache.fro.gui.run.modules.DaggerFroComponent; import ch.gtache.fro.gui.run.modules.DaggerFroComponent;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.Scene; import javafx.scene.Scene;
@@ -13,14 +14,15 @@ import java.io.IOException;
public final class FroApplication extends Application { public final class FroApplication extends Application {
@Override @Override
public void start(final Stage stage) throws IOException { public void start(final Stage primaryStage) throws IOException {
final var component = DaggerFroComponent.create(); final var component = DaggerFroComponent.create();
component.initializers().forEach(Initializer::initialize);
final var loader = component.getMainLoader(); final var loader = component.getMainLoader();
loader.load(); loader.load();
stage.setScene(new Scene(loader.getRoot())); primaryStage.setScene(new Scene(loader.getRoot()));
stage.sizeToScene(); primaryStage.sizeToScene();
stage.setWidth(820); primaryStage.setWidth(820);
stage.setHeight(900); primaryStage.setHeight(900);
stage.show(); primaryStage.show();
} }
} }
@@ -7,7 +7,7 @@ import org.apache.logging.log4j.Logger;
/** /**
* The main class * The main class
*/ */
public final class Main { final class Main {
private static final Logger logger = LogManager.getLogger(Main.class); private static final Logger logger = LogManager.getLogger(Main.class);
@@ -19,7 +19,7 @@ public final class Main {
* *
* @param args the command line arguments * @param args the command line arguments
*/ */
public static void main(final String[] args) { static void main(final String[] args) {
Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception on thread {}", t, e)); Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception on thread {}", t, e));
Application.launch(FroApplication.class, args); Application.launch(FroApplication.class, args);
} }
@@ -1,7 +1,10 @@
package ch.gtache.fro.gui.run.modules; package ch.gtache.fro.gui.run.modules;
import ch.gtache.fro.Initializer;
import ch.gtache.fro.modules.database.DatabaseModule;
import ch.gtache.fro.modules.gui.fx.FXModule; import ch.gtache.fro.modules.gui.fx.FXModule;
import ch.gtache.fro.modules.gui.impl.GuiCoreModule; import ch.gtache.fro.modules.gui.impl.GuiCoreModule;
import ch.gtache.fro.modules.h2.H2Module;
import ch.gtache.fro.modules.impl.CoreModule; import ch.gtache.fro.modules.impl.CoreModule;
import ch.gtache.fro.modules.oiseaux.net.OiseauxNetModule; import ch.gtache.fro.modules.oiseaux.net.OiseauxNetModule;
import ch.gtache.fro.modules.vogelwarte.VogelwarteModule; import ch.gtache.fro.modules.vogelwarte.VogelwarteModule;
@@ -9,8 +12,10 @@ import dagger.Component;
import jakarta.inject.Singleton; import jakarta.inject.Singleton;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import java.util.Set;
@Singleton @Singleton
@Component(modules = {CoreModule.class, GuiCoreModule.class, FXModule.class, VogelwarteModule.class, OiseauxNetModule.class}) @Component(modules = {CoreModule.class, DatabaseModule.class, FXModule.class, GuiCoreModule.class, H2Module.class, OiseauxNetModule.class, VogelwarteModule.class,})
public interface FroComponent { public interface FroComponent {
/** /**
@@ -19,5 +24,12 @@ public interface FroComponent {
* @return the FXMLLoader * @return the FXMLLoader
*/ */
FXMLLoader getMainLoader(); FXMLLoader getMainLoader();
/**
* Returns the initializers for the application
*
* @return The initializers
*/
Set<Initializer> initializers();
} }
+1
View File
@@ -4,6 +4,7 @@
module ch.gtache.fro.gui.run { module ch.gtache.fro.gui.run {
requires ch.gtache.fro.gui.fx; requires ch.gtache.fro.gui.fx;
requires ch.gtache.fro.core; requires ch.gtache.fro.core;
requires ch.gtache.fro.h2;
requires java.compiler; requires java.compiler;
requires javafx.graphics; requires javafx.graphics;
requires javafx.fxml; requires javafx.fxml;
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>fro-h2</artifactId>
<properties>
<h2.version>2.4.240</h2.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-database</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,4 @@
package ch.gtache.fro.h2;
public class H2ConfigurationManager {
}
@@ -0,0 +1,38 @@
package ch.gtache.fro.modules.h2;
import dagger.Module;
import dagger.Provides;
import jakarta.inject.Singleton;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Dagger module for H2
*/
@Module
public final class H2Module {
private H2Module() {
}
@Provides
@Singleton
static Connection providesJdbcConnection() {
try {
final var connection = DriverManager.getConnection("jdbc:h2:mem:");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
connection.close();
} catch (final SQLException e) {
throw new RuntimeException("Error closing H2 connection", e);
}
}));
return connection;
} catch (final SQLException e) {
throw new RuntimeException("Error connecting to H2", e);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
/**
* H2 module for the FRO application
*/
module ch.gtache.fro.h2 {
requires transitive ch.gtache.fro.database;
exports ch.gtache.fro.h2;
exports ch.gtache.fro.modules.h2;
}
@@ -31,7 +31,7 @@ final class BirdTranslationsFetcher {
* *
* @param args command line arguments * @param args command line arguments
*/ */
public static void main(final String[] args) throws Exception { static void main(final String[] args) throws Exception {
final var options = new ChromeOptions(); final var options = new ChromeOptions();
options.addArguments("--headless=new"); options.addArguments("--headless=new");
final var driver = new ChromeDriver(options); final var driver = new ChromeDriver(options);
@@ -7,7 +7,6 @@ import ch.gtache.fro.Fetcher;
import ch.gtache.fro.FetcherConfiguration; import ch.gtache.fro.FetcherConfiguration;
import ch.gtache.fro.PictureType; import ch.gtache.fro.PictureType;
import ch.gtache.fro.SoundType; import ch.gtache.fro.SoundType;
import ch.gtache.fro.impl.CommonBirds;
import ch.gtache.fro.modules.oiseaux.net.OiseauxNet; import ch.gtache.fro.modules.oiseaux.net.OiseauxNet;
import ch.gtache.fro.selenium.AbstractSeleniumFetcher; import ch.gtache.fro.selenium.AbstractSeleniumFetcher;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -64,7 +63,7 @@ public class OiseauxNetFetcher extends AbstractSeleniumFetcher {
@Override @Override
protected void download(final Bird bird) throws FetchException { protected void download(final Bird bird) throws FetchException {
if (bird != CommonBirds.MESANGE_ALPESTRE && bird != CommonBirds.MESANGE_DES_SAULES) { if (!bird.name().equalsIgnoreCase("MESANGE_ALPESTRE") && !bird.name().equalsIgnoreCase("MESANGE_DES_SAULES")) {
downloadImages(bird); downloadImages(bird);
downloadSounds(bird); downloadSounds(bird);
} }
+16 -3
View File
@@ -10,17 +10,20 @@
<module>api</module> <module>api</module>
<module>chant-oiseaux-fr</module> <module>chant-oiseaux-fr</module>
<module>core</module> <module>core</module>
<module>database</module>
<module>gui</module> <module>gui</module>
<module>oiseaux-net</module> <module>h2</module>
<module>vogelwarte</module>
<module>jsoup</module> <module>jsoup</module>
<module>oiseaux-net</module>
<module>utils</module>
<module>vogelwarte</module>
<module>selenium</module> <module>selenium</module>
</modules> </modules>
<properties> <properties>
<compiler-plugin.version>3.14.0</compiler-plugin.version> <compiler-plugin.version>3.14.0</compiler-plugin.version>
<javadoc-plugin.version>3.11.3</javadoc-plugin.version> <javadoc-plugin.version>3.11.3</javadoc-plugin.version>
<maven.compiler.release>24</maven.compiler.release> <maven.compiler.release>25</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<dagger.version>2.57.1</dagger.version> <dagger.version>2.57.1</dagger.version>
@@ -82,6 +85,16 @@
<artifactId>fro-chant-oiseaux-fr</artifactId> <artifactId>fro-chant-oiseaux-fr</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-database</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-h2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>ch.gtache.fro</groupId> <groupId>ch.gtache.fro</groupId>
<artifactId>fro-jsoup</artifactId> <artifactId>fro-jsoup</artifactId>
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>fro-utils</artifactId>
<properties>
<pdfbox.version>3.0.5</pdfbox.version>
<tabula.version>1.0.5</tabula.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.gtache.fro</groupId>
<artifactId>fro-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>technology.tabula</groupId>
<artifactId>tabula</artifactId>
<version>${tabula.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,160 @@
package ch.gtache.fro.utils;
import ch.gtache.fro.PictureType;
import ch.gtache.fro.SoundType;
import ch.gtache.fro.impl.CommonBirds;
import ch.gtache.fro.practice.BirdPracticeParameters;
import ch.gtache.fro.practice.impl.BirdPracticeParametersImpl;
import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.IOException;
import java.text.Normalizer;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Parser of PDF to settings
*/
public class PDFSettingsParser {
private static final Pattern BIRD_PATTERN = Pattern.compile("\\d+ (?<bird>.+?)(?: x)+");
private static final Pattern DIACRITICS_PATTERN = Pattern.compile("\\p{M}");
private static final Set<String> FETCHERS = Set.of("Vogelwarte", "chant-oiseaux.fr", "oiseaux.net");
private static final Set<String> FRO1_SONGS = Set.of("PIGEON_RAMIER", "TOURTERELLE_TURQUE", "COUCOU_GRIS",
"PIC_VERT", "PIC_EPEICHE", "LORIOT_D_EUROPE", "GEAI_DES_CHENES", "MESANGE_NOIRE", "MESANGE_BLEUE",
"MESANGE_CHARBONNIERE", "ALOUETTE_DES_CHAMPS", "HIRONDELLE_RUSTIQUE", "POUILLOT_FITIS", "POUILLOT_VELOCE",
"ROUSSEROLLE_EFFARVATTE", "ROUSSEROLLE_TURDOIDE", "FAUVETTE_A_TETE_NOIRE", "ROITELET_HUPPE", "TROGLODYTE_MIGNON",
"SITTELLE_TORCHEPOT", "GRIMPEREAU_DES_JARDINS", "ETOURNEAU_SANSONNET", "GRIVE_DRAINE", "GRIVE_MUSICIENNE",
"MERLE_NOIR", "ROUGEGORGE_FAMILIER", "ROSSIGNOL_PHILOMELE", "ROUGEQUEUE_NOIR", "BERGERONNETTE_GRISE",
"PINSON_DES_ARBRES", "VERDIER_D_EUROPE", "CHARDONNERET_ELEGANT", "SERIN_CINI", "BRUANT_JAUNE");
private static final Set<PictureType> FRO1_PICTURES = Set.of(PictureType.ADULT, PictureType.ADULT_FEMALE, PictureType.ADULT_MALE,
PictureType.ADULT_INTERNUPTIAL, PictureType.ADULT_INTERNUPTIAL_MALE, PictureType.ADULT_INTERNUPTIAL_FEMALE,
PictureType.ADULT_NUPTIAL, PictureType.ADULT_NUPTIAL_MALE, PictureType.ADULT_NUPTIAL_FEMALE,
PictureType.DARK_MORPH, PictureType.LIGHT_MORPH,
PictureType.UNKNOWN);
private static final Set<SoundType> FRO1_SOUNDS = Set.of(SoundType.SONG, SoundType.UNKNOWN);
private PDFSettingsParser() {
}
private List<BirdPracticeParameters> parseParameters(final String path) throws IOException {
try (final var document = loadDocument(path)) {
final var stripper = new PDFTextStripper();
stripper.setSortByPosition(true);
final var text = stripper.getText(document);
final var matcher = BIRD_PATTERN.matcher(text);
final var parameters = new HashMap<String, BirdPracticeParameters>(CommonBirds.values().length);
for (final var value : CommonBirds.values()) {
parameters.put(value.name(), new BirdPracticeParametersImpl(value, false, Set.of(), Set.of(), Set.of()));
}
while (matcher.find()) {
final var birdName = matcher.group("bird");
final var fixedName = DIACRITICS_PATTERN.matcher(Normalizer.normalize(birdName, Normalizer.Form.NFKD))
.replaceAll("").replace(" ", "_").replace("", "_")
.replace("'", "_").replace("-", "_").toUpperCase(Locale.ROOT)
.replace("ORITE", "MESANGE").replace("LUSCINOIDE", "LUSCINIOIDE")
.replace("GROS_BEC", "GROSBEC");
final var bird = CommonBirds.valueOf(fixedName);
if (FRO1_SONGS.contains(bird.name())) {
parameters.put(bird.name(), new BirdPracticeParametersImpl(bird, true, FETCHERS, FRO1_PICTURES, FRO1_SOUNDS));
} else {
parameters.put(bird.name(), new BirdPracticeParametersImpl(bird, true, FETCHERS, FRO1_PICTURES, Set.of()));
}
}
return parameters.values().stream().sorted(Comparator.comparing(p -> p.bird().name())).toList();
}
}
private static PDDocument loadDocument(final String path) throws IOException {
final var parser = new PDFParser(new RandomAccessReadBufferedFile(path));
return parser.parse();
}
static void main(final String[] args) throws IOException {
final var parser = new PDFSettingsParser();
final var parameters = parser.parseParameters(args[0]);
// System.out.println("INSERT INTO bird_parameters(profile_id, bird_id, enabled) VALUES " + parameters.stream().map(p -> "((SELECT id FROM profile WHERE name='FRO1'), (SELECT id FROM bird WHERE name='" + p.bird() + "'), " + p.enabled() + ")").collect(Collectors.joining(", \n")) + ";");
// System.out.println("INSERT INTO bird_parameters_picture_type(bird_parameters_id, picture_type_id) VALUES " + parameters.stream().filter(p -> p.enabled() && !p.enabledPictureTypes().isEmpty()).flatMap(p -> p.enabledPictureTypes().stream().sorted().map(pt -> "((SELECT id FROM bird_parameters WHERE bird_id=(SELECT id FROM bird WHERE name='" + p.bird() + "') AND profile_id=(SELECT id FROM profile WHERE name='FRO1')), (SELECT id FROM picture_type WHERE name='" + pt.name() + "'))")).collect(Collectors.joining(", \n")) + ";");
// System.out.println("INSERT INTO bird_parameters_sound_type(bird_parameters_id, sound_type_id) VALUES " + parameters.stream().filter(p -> p.enabled() && !p.enabledSoundTypes().isEmpty()).flatMap(p -> p.enabledSoundTypes().stream().sorted().map(st -> "((SELECT id FROM bird_parameters WHERE bird_id=(SELECT id FROM bird WHERE name='" + p.bird() + "') AND profile_id=(SELECT id FROM profile WHERE name='FRO1')), (SELECT id FROM sound_type WHERE name='" + st.name() + "'))")).collect(Collectors.joining(", \n")) + ";");
System.out.println("INSERT INTO bird_parameters_fetcher(bird_parameters_id, fetcher_id) VALUES " + parameters.stream().filter(p -> p.enabled() && !p.enabledFetchers().isEmpty()).flatMap(p -> p.enabledFetchers().stream().sorted().map(f -> "((SELECT id FROM bird_parameters WHERE bird_id=(SELECT id FROM bird WHERE name='" + p.bird() + "') AND profile_id=(SELECT id FROM profile WHERE name='FRO1')), (SELECT id FROM fetcher WHERE name='" + f + "'))")).collect(Collectors.joining(", \n")) + ";");
/* System.out.printf("""
WITH profile_cte AS (SELECT id AS profile_id
FROM profile
WHERE name = 'FRO1'),
bird_cte AS (SELECT name, id AS bird_id
FROM bird)
INSERT
INTO bird_parameters(profile_id, bird_id, enabled)
SELECT p.profile_id, b.bird_id, v.enabled
FROM profile_cte p
JOIN (VALUES %s) AS v(bird_name, enabled) JOIN bird_cte b on B.name = v.bird_name;%n""", parameters.stream().map(s -> "('" + s.bird() + "', " + s.enabled() + ")").collect(Collectors.joining(",\n")));
System.out.printf("""
WITH profile_cte AS (
SELECT id AS profile_id FROM profile WHERE name = 'FRO1'
),
bird_cte AS (
SELECT name AS bird_name, id AS bird_id FROM bird
),
picture_type_cte AS (
SELECT name AS picture_type_name, id AS picture_type_id FROM picture_type
),
bird_parameters_cte AS (
SELECT bp.id AS bird_parameters_id, b.name AS bird_name
FROM bird_parameters bp
JOIN bird b ON bp.bird_id = b.id
WHERE bp.profile_id = (SELECT profile_id FROM profile_cte)
),
pairs AS (
SELECT * FROM (
VALUES
%s
) AS tmp(bird_name, picture_type_name)
)
INSERT INTO bird_parameters_picture_type (bird_parameters_id, picture_type_id)
SELECT
bp.bird_parameters_id,
pt.picture_type_id
FROM pairs p
JOIN bird_parameters_cte bp ON bp.bird_name = p.bird_name
JOIN picture_type_cte pt ON pt.picture_type_name = p.picture_type_name;%n""", parameters.stream().flatMap(s -> s.enabledPictureTypes().stream().map(pt -> "('" + s.bird() + "', '" + pt.name() + "')")).collect(Collectors.joining(",\n")));
System.out.printf("""
WITH profile_cte AS (
SELECT id AS profile_id FROM profile WHERE name = 'FRO1'
),
bird_cte AS (
SELECT name AS bird_name, id AS bird_id FROM bird
),
sound_type_cte AS (
SELECT name AS sound_type_name, id AS sound_type_id FROM sound_type
),
bird_parameters_cte AS (
SELECT bp.id AS bird_parameters_id, b.name AS bird_name
FROM bird_parameters bp
JOIN bird b ON bp.bird_id = b.id
WHERE bp.profile_id = (SELECT profile_id FROM profile_cte)
),
pairs AS (
SELECT * FROM (
VALUES
%s
) AS tmp(bird_name, sound_type_name)
)
INSERT INTO bird_parameters_sound_type (bird_parameters_id, sound_type_id)
SELECT
bp.bird_parameters_id,
st.sound_type_id
FROM pairs p
JOIN bird_parameters_cte bp ON bp.bird_name = p.bird_name
JOIN sound_type_cte st ON st.sound_type_name = p.sound_type_name;%n""", parameters.stream().flatMap(s -> s.enabledSoundTypes().stream().map(st -> "('" + s.bird() + "', '" + st.name() + "')")).collect(Collectors.joining(",\n")));*/
}
}