Generator für Stellenanzeigen

vorhergehende Artikel in: Java Software-Test Komponenten
27.09.2023

Ich habe neulich wieder einmal einen neuen Testdatengenerator geschrieben, den ich mit Daten aus der Perrypedia fütterte.

Inspiriert wurde ich von einem Generator für Jobangebote im Startrek-Universum.

Und da ich immer noch der Meinung bin, dass LLMs eine pure Verschwendung von Ressourcen sind wollte ich sehen, ob ich mit einer einfachen Markovkette nicht etwas ähnliches schaffen könnte.

Um die Datenquellen nicht über Gebühr zu belasten erstellte ich zunächst eine Klasse, die eine Datei aus dem Netz herunterlädt und lokal chached. Dies sollte für den Anwendungscode vollständig transparent geschehen. Der Code sollte dabei die Angaben zur Lebenszeit der Ressource berücksichtigen und entsprechend der Informationen vom Server automatisch eine neue Version herunterladen wenn diese abgelaufen wäre.

Dabei kam der folgende Code heraus:

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.time.Clock;

public class CachedAndDownloadedResource extends java.lang.Object { private final static org.slf4j.Logger CLASS_LOGGER =org.slf4j.LoggerFactory.getLogger(CachedAndDownloadedResource.class); private final static org.slf4j.Logger EXCEPTION_LOGGER =org.slf4j.LoggerFactory.getLogger("ExceptionCatcher");

private final java.net.URL url; private final java.io.File cachedFile; private final long maxAgeInSeconds;

public CachedAndDownloadedResource(java.net.URL url) throws NoSuchAlgorithmException, IOException { this(url,-1); } public CachedAndDownloadedResource(java.net.URL url, long maxAgeInSeconds) throws NoSuchAlgorithmException, IOException { super(); if(url==null) throw new java.lang.IllegalArgumentException("url must not be null!"); this.url=url; this.maxAgeInSeconds=maxAgeInSeconds; java.lang.String urls=url.toString(); java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-512"); byte[] encodedhash = digest.digest(urls.getBytes(java.nio.charset.StandardCharsets.UTF_8)); java.lang.String hash=de.elbosso.util.Utilities.formatHexDump(encodedhash,false); CLASS_LOGGER.debug(java.text.MessageFormat.format("encodedhash {0}",hash)); java.io.File cacheDir=de.elbosso.util.Utilities.getCacheDirectory(); cachedFile=new java.io.File(cacheDir,hash); java.net.URLConnection conn=de.elbosso.util.Utilities.openConnectionFollowingRedirects(url); java.lang.String cacheControl=conn.getHeaderField("Cache-Control"); CLASS_LOGGER.debug(java.text.MessageFormat.format("Cache-Control for {0} is {1}",url,cacheControl)); if(((cacheControl.contains("private"))||(cacheControl.contains("must-revalidate")))&&(maxAgeInSeconds<1)) { CLASS_LOGGER.debug("caching not allowed!"); } else { if (cachedFile.exists() == false) { download(); } else { CLASS_LOGGER.debug(java.text.MessageFormat.format("found cached file for {0}", url)); java.time.Instant fileInstant = java.nio.file.Files.getLastModifiedTime(java.nio.file.Paths.get(cachedFile.toURI())).toInstant(); java.time.Instant now = Clock.systemDefaultZone().instant(); java.time.Duration difference = java.time.Duration.between(fileInstant, now); long millis = difference.toMillis(); CLASS_LOGGER.debug(java.text.MessageFormat.format("cached file is {0} seconds old", (millis / 1000))); java.lang.String[] parts = cacheControl.split(","); long maxAge = maxAgeInSeconds; for (java.lang.String part : parts) { if (part.startsWith("max-age=")) { long time=java.lang.Long.parseLong(part.substring(8)); if(maxAge>time) maxAge=time; break; } } CLASS_LOGGER.debug(java.text.MessageFormat.format("max age of {0} is {1}", url, maxAge)); if (maxAge > -1) { if (maxAge < millis / 1000) { download(); } } } } } private void download() throws IOException { CLASS_LOGGER.debug(java.text.MessageFormat.format("downloading from {0}", url)); java.io.FileOutputStream fos = new java.io.FileOutputStream(cachedFile); de.elbosso.util.Utilities.copyFromURLIntoStream(url, fos, true, true); } public java.io.InputStream openStream() throws IOException { java.io.InputStream rv=cachedFile!=null?new java.io.FileInputStream(cachedFile):null; if(rv!=null) { rv=de.elbosso.util.Utilities.openConnectionFollowingRedirects(url).getInputStream(); } return rv; } public java.time.Instant getLastModifiedDate() throws IOException { return cachedFile!=null?java.nio.file.Files.getLastModifiedTime(java.nio.file.Paths.get(cachedFile.toURI())).toInstant():java.time.Instant.now(Clock.systemDefaultZone()); } }

Damit war es mir möglich, die benötigten Daten für den Generator einzusammeln, was dann zu folgenden Beispielen für Stellenanzeigen im Peryversum führte:

Politbüro 610 sucht  ab sofort ein Team von 3 Mitarbeitern, darunter 
mindestens ein Paradimingenieur, idealerweise ein weiterer Historiker. Bewerber 
von folgenden Welten oder vergleichbaren Umweltbedingungen werden bevorzugt 
berücksichtigt: Strega und Drackrioch. Erfahrungen bezüglich Audikom und 
Zweikomponenten-Absorber von mindestens 1 Standardjahren müssen zwingend nachgewiesen 
werden.  Der Vertrag ist unbefristed. Die Stationierung erfolgt an Bord von KABBACH 
- Dienstantritt erfolgt auf Central-Station. Bewerber kontaktieren bitte umgehend 
Algiotische Wanderer. Ihre Bewerbung wird zentral gesammelt und an Ti-Than 
zur Bearbeitung weitergeleitet.
Für eine Expedition in Richtung Milchstraße suchen wir für nächstes Jahr
einen Planforming-Ingenieur. Bewerber aus den Völkern Pers-Oggaren, Treidever, 
Argots und Truzenen oder vergleichbaren Umweltbedingungen von Vorteil. 
Kenntnisse bezüglich Individualschloss, Positronischer Schlüssel, Strukturabsorber 
und Biogen-Regenerator von Vorteil. Erfahrungen bezüglich Hypertraktor und 
Estartische Technik von mindestens 10 Standardjahren müssen zwingend nachgewiesen 
werden.  Der Vertrag ist unbefristed. Die Stationierung erfolgt an Bord von 
BOX-3206 - Dienstantritt erfolgt auf Lysum 1.
Damurial sucht  für nächstes Jahr ein Team von 2 Mitarbeitern, darunter
mindestens ein Waffeningenieur, idealerweise ein weiterer Butler. Bewerber 
aus den Völkern Koyter, Obugaab, Skaerhams und Craahzz oder vergleichbaren 
Umweltbedingungen von Vorteil. Geplante Dauer das Vertrages: 31 solare Monate 
mit Option auf Verlängerung. Die Stationierung erfolgt an Bord von RALPH 
SIKERON - Dienstantritt erfolgt auf GEUZA. Bewerber kontaktieren bitte 
umgehend Fracowitz-Systemstaaten. Ihre Bewerbung wird zentral gesammelt und 
an Space Academy zur Bearbeitung weitergeleitet.
Wegen Stigmavirus sucht Unionsrat ab sofort einen Psychochirurg.
Bewerber aus den Völkern Peikomäer, Karoky und Kraqueker oder vergleichbaren 
Umweltbedingungen von Vorteil. Kenntnisse in Sprache und Sozialstruktur 
folgender Völker sind extrem hilfreich: Barbassen, Vendoori und Skinen.  
 Der Vertrag ist unbefristed. Einsatzort ist TV-8-Sol mit gelegentlichen 
Abordnungen. Bewerber kontaktieren bitte umgehend Koalition Thoregon. Ihre 
Bewerbung wird zentral gesammelt und an Extraterrestrial Field Service 
zur Bearbeitung weitergeleitet.
Wegen Explosive Zellteilung suchen wir für nächstes Jahr ein Team von 4
Mitarbeitern, darunter mindestens ein Planformarchitekt, idealerweise ein 
weiterer Trümmerscout. Bewerber von folgenden Welten oder vergleichbaren 
Umweltbedingungen werden bevorzugt berücksichtigt: Taffstav, Kolton und 
Rasterstop III. Kenntnisse bezüglich Psionischer Stempel und Totenbrünne 
von Vorteil. Erfahrungen bezüglich Ishara und Antipsischirm von mindestens 
15 Standardjahren müssen zwingend nachgewiesen werden.  Der Vertrag ist 
unbefristed. Einsatzort ist Bressor

Artikel, die hierher verlinken

Generator für syntaktisch korrekten Python Code

01.11.2024

Nachdem es nun bereits seit einiger Zeit ein wenig stiller um meine diversen Generatoren für Testdaten geworden ist, habe ich über den Feiertag in Thüringen einen neuen begonnen.

Alle Artikel rss Wochenübersicht Monatsübersicht Codeberg Repositories Mastodon Über mich home xmpp


Vor 5 Jahren hier im Blog

  • Multi-User-WebDAV, Docker, GitHub

    17.11.2019

    Nachdem ich mich in letzter Zeit verstärkt mit Docker und dem zugehörigen Ökosystem beschäftige, habe ich begonnen, verschiedenste Dienste in Containern zu testen um zu sehen, ob in manchen Fällen LXC oder KVM nicht doch die bessere Wahl wäre...

    Weiterlesen...

Neueste Artikel

  • Migration der Webseite und aller OpenSource Projekte

    In eigener Sache...

    Weiterlesen...
  • AutoHideToolbar für Java Swing

    Ich habe eine neue Java Swing Komponente erstellt: Es handelt sich um einen Wrapper für von JToolBar abgeleitete Klassen, die die Werkzeugleiste minimieren und sie nur dann einblenden, wenn der Mauszeiger über ihnen schwebt.

    Weiterlesen...
  • Integration von EBMap4D in die sQLshell

    Ich habe bereits in einem früheren Artikel über meine ersten Erfolge berichtet, der sQLshell auf Basis des bestehenden Codes aus dem Projekt EBMap4D eine bessere Integration für Geo-Daten zu spendieren und entsprechende Abfragen, bzw. deren Ergebnisse auf einer Kartenansicht zu visualisieren.

    Weiterlesen...

Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.

Wer daran teilhaben und eventuell sogar davon profitieren möchte, muss damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.

Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...

PS: Meine öffentlichen Codeberg-Repositories findet man hier.