update impressum & privacy policy

pull/251/merge
Jon Eugster 2 years ago
parent a1b1a33a9b
commit eac945e7b5

@ -23,7 +23,6 @@
"Editor mode is enforced!": "Editor kann nicht verlassen werden!", "Editor mode is enforced!": "Editor kann nicht verlassen werden!",
"Editor mode": "Editor", "Editor mode": "Editor",
"Typewriter mode": "Schreibmaschine", "Typewriter mode": "Schreibmaschine",
"information, Impressum, privacy policy": "Informationen, Impressum, Privacy Policy",
"Preferences": "Einstellungen", "Preferences": "Einstellungen",
"Game Info & Credits": "Spielinfo & Credits", "Game Info & Credits": "Spielinfo & Credits",
"Game Info": "Spielinfo", "Game Info": "Spielinfo",
@ -91,5 +90,11 @@
"Retry proof from here": "Ab hier erneut versuchen", "Retry proof from here": "Ab hier erneut versuchen",
"Retry": "", "Retry": "",
"Failed command": "Befehl fehlgeschlagen", "Failed command": "Befehl fehlgeschlagen",
"view the Lean game server on Github": "Lean game Server auf Github ansehen" "view the Lean game server on Github": "Lean game Server auf Github ansehen",
"Theorem": "Theorem",
"Impressum": "Impressum",
"Privacy Policy": "Datenschutzerklärung",
"<0>Impressum</0><1><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></1><2><strong>Legal form:</strong><br/>The Heinrich Heine University Düsseldorf is a corporation under public law. It is legally represented by the Rector Prof. Dr. Anja Steinbeck. The responsible supervisory authority is the Ministry of Culture and Science of North Rhine-Westphalia, Völklinger Straße 49, 40221 Düsseldorf.</2><3><strong>VAT identification number:</strong><br/>according to §27a Sales Tax Act<br/>DE 811222416</3><4><0>Impressum HHU</0></4>": "<0>Impressum</0><1><strong>Kontakt:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Deutschland<br/>+49 211 81-14690<br/><14>Kontaktinformationen</14></1><2><strong>Rechtsform:</strong><br />Die Heinrich-Heine Universität Düsseldorf ist eine Körperschaft des Öffentlichen Rechts. Sie wird durch die Rektorin Prof. Dr. Anja Steinbeck gesetzlich vertreten. Zuständige Aufsichtsbehörde ist das Ministerium für Kultur und Wissenschaft des Landes Nordrhein-Westfalen, Völklinger Straße 49, 40221 Düsseldorf.</2><3><strong>Umsatzsteuer-Identifikationsnummer:</strong><br />gemäß §27a Umsatzsteuergesetz<br />DE 811222416</3><4><0>Impressum der HHU</0></4>",
"<0>Progress saving</0><1>The game stores your progress in your local browser storage. If you delete it, your progress will be lost!<br/>Warning: In most browsers, deleting cookies will also clear the local storage (or \"local site data\"). Make sure to download your game progress first!</1><2>Development</2><3>The game engine has been created by <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>. On a prototype by <strong>Patrick Massot</strong>.</3><4>The source code of this Lean game engine is <1>available on Github</1>. If you experience any problems, please file an <3>Issue on Github</3> or get directly in contact.</4><5>Funding</5><6>The game engine has been developed as part of the project <1>ADAM: Anticipating the Digital Age of Mathematics</1> at Heinrich-Heine-Universität Düsseldorf. It is funded by the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.</6>": "<0>Spielstandspeicherung</0><1>Das Spiel speichert den Spielstand im lokalen Browserspeicher. Wird dieser gelöscht, ist der Spielstand nicht wiederherstellbar!<br/>Achtung: In üblichen Browsern bewirkt ein löschen von Cookies auch ein löschen des lokalen Browserspeichers (z.B. \"local site data\"). Der Spielstand sollte vorgehend heruntergeladen werden!</1><2>Entwicklung</2><3>Der Spieleserver wurde entwickelt von <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>. Basierend auf einem Prototyp von <strong>Patrick Massot</strong>.</3><4>Der Sourcecode dieses Lean-Game-Engine ist <1>auf Github verfügbar</1>. Bei Problemen, bitte einen <3>Github-Issue</3> ausfüllen oder direkt mit uns Kontakt aufnehmen.</4><5>Funding</5><6>Dieser Spielserver wurde im Rahmen des Projekts <1>ADAM: Anticipating the Digital Age of Mathematics</1> an der Heinrich-Heine-Universität Düsseldorf entwickelt. Es wird finanziell durch das Projekt <i>Freiraum 2022</i> der <i>Stiftung Innovation in der Hochschullehre</i> unterstützt.</6>",
"<0>Privacy Policy</0><p>Our server collects metadata (such as IP address, browser, operating system) and the data that the user enters into the editor. The data is used to compute the Lean output and display it to the user. The information will be stored as long as the user stays on our website and will be deleted immediately afterwards. We keep logs to improve our software, but the contained data is anonymized.</p><p>We do not use cookies, but your game progress is stored in the browser as site data. Your game progress is not saved on the server; if you delete your browser storage, it is completely gone.</p><p>Our server is located in Germany.</p><4><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></4>": "<0>Datenschutzerklärung</0><p>Unser Server verarbeitet Benutzer-Metadaten (zum Beispiel IP-Addresse, Browser-Version, Betriebssystem) sowie die Benutzereingaben in den Editor. Diese Daten werden verwendet um die Lean-Ausgabe zu berechnen und dem Benutzer darzustellen. Die Informationen werden nur gespeichert, solange der Benutzer auf unserer Webseite bleibt und anschliessend sofort gelöscht. Wir führen Log-Dateien um die Software zu verbessern, aber die enthaltenen Daten sind anonymisiert.</p><p>Wir verwenden keine Cookies, aber der Spielstand wird im Browser als \"Site Data\" gespeichert. Der Spielstand wird nicht auf dem Server gespeichert; wird er lokal gelöscht, kann er nicht wiederhergestellt werden.</p><p>Unser Server ist in Deutschland stationiert.</p><4><strong>Kontakt:</strong><br/>Markus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Deutschland<br/>+49 211 81-14690<br/><14>Kontaktdetails</14></4>"
} }

@ -23,7 +23,6 @@
"Editor mode is enforced!": "Editor mode is enforced!", "Editor mode is enforced!": "Editor mode is enforced!",
"Editor mode": "Editor mode", "Editor mode": "Editor mode",
"Typewriter mode": "Typewriter mode", "Typewriter mode": "Typewriter mode",
"information, Impressum, privacy policy": "information, Impressum, privacy policy",
"Preferences": "Preferences", "Preferences": "Preferences",
"Game Info & Credits": "Game Info & Credits", "Game Info & Credits": "Game Info & Credits",
"Game Info": "Game Info", "Game Info": "Game Info",
@ -91,5 +90,11 @@
"Retry proof from here": "Retry proof from here", "Retry proof from here": "Retry proof from here",
"Retry": "Retry", "Retry": "Retry",
"Failed command": "Failed command", "Failed command": "Failed command",
"view the Lean game server on Github": "view the Lean game server on Github" "view the Lean game server on Github": "view the Lean game server on Github",
"Theorem": "Theorem",
"Impressum": "Impressum",
"Privacy Policy": "Privacy Policy",
"<0>Impressum</0><1><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></1><2><strong>Legal form:</strong><br/>The Heinrich Heine University Düsseldorf is a corporation under public law. It is legally represented by the Rector Prof. Dr. Anja Steinbeck. The responsible supervisory authority is the Ministry of Culture and Science of North Rhine-Westphalia, Völklinger Straße 49, 40221 Düsseldorf.</2><3><strong>VAT identification number:</strong><br/>according to §27a Sales Tax Act<br/>DE 811222416</3><4><0>Impressum HHU</0></4>": "<0>Impressum</0><1><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></1><2><strong>Legal form:</strong><br/>The Heinrich Heine University Düsseldorf is a corporation under public law. It is legally represented by the Rector Prof. Dr. Anja Steinbeck. The responsible supervisory authority is the Ministry of Culture and Science of North Rhine-Westphalia, Völklinger Straße 49, 40221 Düsseldorf.</2><3><strong>VAT identification number:</strong><br/>according to §27a Sales Tax Act<br/>DE 811222416</3><4><0>Impressum HHU</0></4>",
"<0>Progress saving</0><1>The game stores your progress in your local browser storage. If you delete it, your progress will be lost!<br/>Warning: In most browsers, deleting cookies will also clear the local storage (or \"local site data\"). Make sure to download your game progress first!</1><2>Development</2><3>The game engine has been created by <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>. On a prototype by <strong>Patrick Massot</strong>.</3><4>The source code of this Lean game engine is <1>available on Github</1>. If you experience any problems, please file an <3>Issue on Github</3> or get directly in contact.</4><5>Funding</5><6>The game engine has been developed as part of the project <1>ADAM: Anticipating the Digital Age of Mathematics</1> at Heinrich-Heine-Universität Düsseldorf. It is funded by the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.</6>": "<0>Progress saving</0><1>The game stores your progress in your local browser storage. If you delete it, your progress will be lost!<br/>Warning: In most browsers, deleting cookies will also clear the local storage (or \"local site data\"). Make sure to download your game progress first!</1><2>Development</2><3>The game engine has been created by <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>. On a prototype by <strong>Patrick Massot</strong>.</3><4>The source code of this Lean game engine is <1>available on Github</1>. If you experience any problems, please file an <3>Issue on Github</3> or get directly in contact.</4><5>Funding</5><6>The game engine has been developed as part of the project <1>ADAM: Anticipating the Digital Age of Mathematics</1> at Heinrich-Heine-Universität Düsseldorf. It is funded by the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.</6>",
"<0>Privacy Policy</0><p>Our server collects metadata (such as IP address, browser, operating system) and the data that the user enters into the editor. The data is used to compute the Lean output and display it to the user. The information will be stored as long as the user stays on our website and will be deleted immediately afterwards. We keep logs to improve our software, but the contained data is anonymized.</p><p>We do not use cookies, but your game progress is stored in the browser as site data. Your game progress is not saved on the server; if you delete your browser storage, it is completely gone.</p><p>Our server is located in Germany.</p><4><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></4>": "<0>Privacy Policy</0><p>Our server collects metadata (such as IP address, browser, operating system) and the data that the user enters into the editor. The data is used to compute the Lean output and display it to the user. The information will be stored as long as the user stays on our website and will be deleted immediately afterwards. We keep logs to improve our software, but the contained data is anonymized.</p><p>We do not use cookies, but your game progress is stored in the browser as site data. Your game progress is not saved on the server; if you delete your browser storage, it is completely gone.</p><p>Our server is located in Germany.</p><4><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></4>"
} }

@ -23,7 +23,6 @@
"Editor mode is enforced!": "编辑器模式开启!", "Editor mode is enforced!": "编辑器模式开启!",
"Editor mode": "编辑器模式", "Editor mode": "编辑器模式",
"Typewriter mode": "打字机模式", "Typewriter mode": "打字机模式",
"information, Impressum, privacy policy": "信息、版权声明 (Impressum)、隐私政策",
"Preferences": "偏好设置", "Preferences": "偏好设置",
"Game Info & Credits": "游戏信息和荣誉", "Game Info & Credits": "游戏信息和荣誉",
"Game Info": "游戏信息", "Game Info": "游戏信息",
@ -91,5 +90,11 @@
"Level": "关卡", "Level": "关卡",
"Introduction": "介绍", "Introduction": "介绍",
"Retry": "重试", "Retry": "重试",
"Failed command": "命令失败" "Failed command": "命令失败",
"view the Lean game server on Github": "",
"Impressum": "版权声明",
"Privacy Policy": "隐私政策",
"<0>Impressum</0><1><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></1><2><strong>Legal form:</strong><br/>The Heinrich Heine University Düsseldorf is a corporation under public law. It is legally represented by the Rector Prof. Dr. Anja Steinbeck. The responsible supervisory authority is the Ministry of Culture and Science of North Rhine-Westphalia, Völklinger Straße 49, 40221 Düsseldorf.</2><3><strong>VAT identification number:</strong><br/>according to §27a Sales Tax Act<br/>DE 811222416</3><4><0>Impressum HHU</0></4>": "",
"<0>Progress saving</0><1>The game stores your progress in your local browser storage. If you delete it, your progress will be lost!<br/>Warning: In most browsers, deleting cookies will also clear the local storage (or \"local site data\"). Make sure to download your game progress first!</1><2>Development</2><3>The game engine has been created by <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>. On a prototype by <strong>Patrick Massot</strong>.</3><4>The source code of this Lean game engine is <1>available on Github</1>. If you experience any problems, please file an <3>Issue on Github</3> or get directly in contact.</4><5>Funding</5><6>The game engine has been developed as part of the project <1>ADAM: Anticipating the Digital Age of Mathematics</1> at Heinrich-Heine-Universität Düsseldorf. It is funded by the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.</6>": "",
"<0>Privacy Policy</0><p>Our server collects metadata (such as IP address, browser, operating system) and the data that the user enters into the editor. The data is used to compute the Lean output and display it to the user. The information will be stored as long as the user stays on our website and will be deleted immediately afterwards. We keep logs to improve our software, but the contained data is anonymized.</p><p>We do not use cookies, but your game progress is stored in the browser as site data. Your game progress is not saved on the server; if you delete your browser storage, it is completely gone.</p><p>Our server is located in Germany.</p><4><strong>Contact:</strong><br/>Marcus Zibrowius, Jon Eugster<br/>Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br/>Universitätsstr. 1<br/>40225 Düsseldorf<br/>Germany<br/>+49 211 81-14690<br/><14>Contact Details</14></4>": ""
} }

@ -123,16 +123,21 @@ function InputModeButton({setNavOpen, isDropdown}) {
</Button> </Button>
} }
/** button to toggle iimpressum popup
*
* Note: Do not translate the word "Impressum"! German GDPR needs this.
*/
export function ImpressumButton({setNavOpen, toggleImpressum, isDropdown}) { export function ImpressumButton({setNavOpen, toggleImpressum, isDropdown}) {
const { t } = useTranslation() const { t } = useTranslation()
return <Button className="btn btn-inverted" return <Button className="btn btn-inverted"
title={t("information, Impressum, privacy policy")} inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}> title={t("Impressum")} inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}>
<FontAwesomeIcon icon={faCircleInfo} /> <FontAwesomeIcon icon={faCircleInfo} />
{isDropdown && <>&nbsp;Impressum</>} {isDropdown && <>&nbsp;{t("Impressum")}</>}
</Button>
}
export function PrivacyButton({setNavOpen, togglePrivacy, isDropdown}) {
const { t } = useTranslation()
return <Button className="btn btn-inverted"
title={t("Privacy Policy")} inverted="true" to="" onClick={(ev) => {togglePrivacy(ev); setNavOpen(false)}}>
<FontAwesomeIcon icon={faCircleInfo} />
{isDropdown && <>&nbsp;{t("Privacy Policy")}</>}
</Button> </Button>
} }
@ -204,11 +209,12 @@ function InventoryButton({pageNumber, setPageNumber}) {
} }
/** the navigation bar on the welcome page */ /** the navigation bar on the welcome page */
export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpressum, toggleEraseMenu, toggleUploadMenu, toggleInfo, togglePreferencesPopup} : { export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpressum, togglePrivacy, toggleEraseMenu, toggleUploadMenu, toggleInfo, togglePreferencesPopup} : {
pageNumber: number, pageNumber: number,
setPageNumber: any, setPageNumber: any,
gameInfo: GameInfo, gameInfo: GameInfo,
toggleImpressum: any, toggleImpressum: any,
togglePrivacy: any,
toggleEraseMenu: any, toggleEraseMenu: any,
toggleUploadMenu: any, toggleUploadMenu: any,
toggleInfo: any, toggleInfo: any,
@ -238,16 +244,18 @@ export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpres
<DownloadButton setNavOpen={setNavOpen} gameId={gameId} gameProgress={gameProgress}/> <DownloadButton setNavOpen={setNavOpen} gameId={gameId} gameProgress={gameProgress}/>
<UploadButton setNavOpen={setNavOpen} toggleUploadMenu={toggleUploadMenu}/> <UploadButton setNavOpen={setNavOpen} toggleUploadMenu={toggleUploadMenu}/>
<ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} /> <ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} />
<PrivacyButton setNavOpen={setNavOpen} togglePrivacy={togglePrivacy} isDropdown={true} />
<PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/> <PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/>
</div> </div>
</div> </div>
} }
/** the navigation bar in a level */ /** the navigation bar in a level */
export function LevelAppBar({isLoading, levelTitle, toggleImpressum, toggleInfo, togglePreferencesPopup, pageNumber=undefined, setPageNumber=undefined} : { export function LevelAppBar({isLoading, levelTitle, toggleImpressum, togglePrivacy, toggleInfo, togglePreferencesPopup, pageNumber=undefined, setPageNumber=undefined} : {
isLoading: boolean, isLoading: boolean,
levelTitle: string, levelTitle: string,
toggleImpressum: any, toggleImpressum: any,
togglePrivacy: any,
toggleInfo: any, toggleInfo: any,
togglePreferencesPopup: any, togglePreferencesPopup: any,
pageNumber?: number, pageNumber?: number,
@ -282,6 +290,7 @@ export function LevelAppBar({isLoading, levelTitle, toggleImpressum, toggleInfo,
<InputModeButton setNavOpen={setNavOpen} isDropdown={true}/> <InputModeButton setNavOpen={setNavOpen} isDropdown={true}/>
<GameInfoButton setNavOpen={setNavOpen} toggleInfo={toggleInfo}/> <GameInfoButton setNavOpen={setNavOpen} toggleInfo={toggleInfo}/>
<ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} /> <ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} />
<PrivacyButton setNavOpen={setNavOpen} togglePrivacy={togglePrivacy} isDropdown={true} />
<PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/> <PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/>
</div> </div>
</> : </> :
@ -303,6 +312,7 @@ export function LevelAppBar({isLoading, levelTitle, toggleImpressum, toggleInfo,
<div className={'menu dropdown' + (navOpen ? '' : ' hidden')}> <div className={'menu dropdown' + (navOpen ? '' : ' hidden')}>
<GameInfoButton setNavOpen={setNavOpen} toggleInfo={toggleInfo}/> <GameInfoButton setNavOpen={setNavOpen} toggleInfo={toggleInfo}/>
<ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} /> <ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} />
<PrivacyButton setNavOpen={setNavOpen} togglePrivacy={togglePrivacy} isDropdown={true} />
<PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/> <PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/>
</div> </div>
</> </>

@ -35,6 +35,12 @@ monaco.languages.register({
extensions: ['.leancmd'] extensions: ['.leancmd']
}) })
// register Monaco languages // TODO: JE. I dont understand why I suddenly had to add this when it worked without before.
monaco.languages.register({
id: 'lean4',
extensions: ['.lean']
})
// map of monaco "language id's" to TextMate scopeNames // map of monaco "language id's" to TextMate scopeNames
const grammars = new Map() const grammars = new Map()
grammars.set('lean4', 'source.lean') grammars.set('lean4', 'source.lean')

@ -11,12 +11,12 @@ import '../css/landing_page.css'
import bgImage from '../assets/bg.jpg' import bgImage from '../assets/bg.jpg'
import Markdown from './markdown'; import Markdown from './markdown';
import {PrivacyPolicyPopup} from './popup/privacy_policy' import {PrivacyPolicyPopup, ImpressumPopup} from './popup/privacy_policy'
import { GameTile, useGetGameInfoQuery } from '../state/api' import { GameTile, useGetGameInfoQuery } from '../state/api'
import path from 'path'; import path from 'path';
import { PreferencesPopup } from './popup/preferences'; import { PreferencesPopup } from './popup/preferences';
import { ImpressumButton, MenuButton, PreferencesButton } from './app_bar'; import { ImpressumButton, MenuButton, PreferencesButton, PrivacyButton } from './app_bar';
import ReactCountryFlag from 'react-country-flag'; import ReactCountryFlag from 'react-country-flag';
import lean4gameConfig from '../config.json' import lean4gameConfig from '../config.json'
import i18next from 'i18next'; import i18next from 'i18next';
@ -91,11 +91,15 @@ function LandingPage() {
const navigate = useNavigate(); const navigate = useNavigate();
const [impressumPopup, setImpressumPopup] = React.useState(false); const [impressumPopup, setImpressumPopup] = React.useState(false);
const [privacyPopup, setPrivacyPopup] = React.useState(false);
const [preferencesPopup, setPreferencesPopup] = React.useState(false); const [preferencesPopup, setPreferencesPopup] = React.useState(false);
const [navOpen, setNavOpen] = React.useState(false); const [navOpen, setNavOpen] = React.useState(false);
const openImpressum = () => setImpressumPopup(true); const openImpressum = () => setImpressumPopup(true);
const closeImpressum = () => setImpressumPopup(false); const closeImpressum = () => setImpressumPopup(false);
const toggleImpressum = () => setImpressumPopup(!impressumPopup); const toggleImpressum = () => setImpressumPopup(!impressumPopup);
const openPrivacy = () => setPrivacyPopup(true);
const closePrivacy = () => setPrivacyPopup(false);
const togglePrivacy = () => setPrivacyPopup(!privacyPopup);
const closePreferencesPopup = () => setPreferencesPopup(false); const closePreferencesPopup = () => setPreferencesPopup(false);
const togglePreferencesPopup = () => setPreferencesPopup(!preferencesPopup); const togglePreferencesPopup = () => setPreferencesPopup(!preferencesPopup);
@ -128,6 +132,7 @@ function LandingPage() {
<MenuButton navOpen={navOpen} setNavOpen={setNavOpen}/> <MenuButton navOpen={navOpen} setNavOpen={setNavOpen}/>
<div className={'menu dropdown' + (navOpen ? '' : ' hidden')}> <div className={'menu dropdown' + (navOpen ? '' : ' hidden')}>
<ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} /> <ImpressumButton setNavOpen={setNavOpen} toggleImpressum={toggleImpressum} isDropdown={true} />
<PrivacyButton setNavOpen={setNavOpen} togglePrivacy={togglePrivacy} isDropdown={true} />
<PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/> <PreferencesButton setNavOpen={setNavOpen} togglePreferencesPopup={togglePreferencesPopup}/>
</div> </div>
</nav> </nav>
@ -214,7 +219,9 @@ function LandingPage() {
<footer> <footer>
{/* Do not translate "Impressum", it's needed for German GDPR */} {/* Do not translate "Impressum", it's needed for German GDPR */}
<a className="link" onClick={openImpressum}>Impressum</a> <a className="link" onClick={openImpressum}>Impressum</a>
{impressumPopup? <PrivacyPolicyPopup handleClose={closeImpressum} />: null} <a className="link" onClick={openPrivacy}>{t("Privacy Policy")}</a>
{privacyPopup? <PrivacyPolicyPopup handleClose={closePrivacy} />: null}
{impressumPopup? <ImpressumPopup handleClose={closeImpressum} />: null}
{preferencesPopup ? <PreferencesPopup handleClose={closePreferencesPopup} /> : null} {preferencesPopup ? <PreferencesPopup handleClose={closePreferencesPopup} /> : null}
</footer> </footer>
</div> </div>

@ -33,7 +33,7 @@ import { DeletedChatContext, InputModeContext, PreferencesContext, MonacoEditorC
import { DualEditor } from './infoview/main' import { DualEditor } from './infoview/main'
import { GameHint, InteractiveGoalsWithHints, ProofState } from './infoview/rpc_api' import { GameHint, InteractiveGoalsWithHints, ProofState } from './infoview/rpc_api'
import { DeletedHints, Hint, Hints, MoreHelpButton, filterHints } from './hints' import { DeletedHints, Hint, Hints, MoreHelpButton, filterHints } from './hints'
import { PrivacyPolicyPopup } from './popup/privacy_policy' import { ImpressumPopup, PrivacyPolicyPopup } from './popup/privacy_policy'
import path from 'path'; import path from 'path';
import '@fontsource/roboto/300.css' import '@fontsource/roboto/300.css'
@ -75,10 +75,12 @@ function Level() {
// pop-ups // pop-ups
const [impressum, setImpressum] = React.useState(false) const [impressum, setImpressum] = React.useState(false)
const [privacy, setPrivacy] = React.useState(false)
const [info, setInfo] = React.useState(false) const [info, setInfo] = React.useState(false)
const [preferencesPopup, setPreferencesPopup] = React.useState(false) const [preferencesPopup, setPreferencesPopup] = React.useState(false)
function closeImpressum() {setImpressum(false)} function closeImpressum() {setImpressum(false)}
function closePrivacy() {setPrivacy(false)}
function closeInfo() {setInfo(false)} function closeInfo() {setInfo(false)}
function closePreferencesPopup() {setPreferencesPopup(false)} function closePreferencesPopup() {setPreferencesPopup(false)}
function toggleImpressum() {setImpressum(!impressum)} function toggleImpressum() {setImpressum(!impressum)}
@ -87,9 +89,10 @@ function Level() {
return <WorldLevelIdContext.Provider value={{worldId, levelId}}> return <WorldLevelIdContext.Provider value={{worldId, levelId}}>
{levelId == 0 ? {levelId == 0 ?
<Introduction impressum={impressum} setImpressum={setImpressum} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup} /> : <Introduction impressum={impressum} setImpressum={setImpressum} privacy={privacy} setPrivacy={setPrivacy} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup} /> :
<PlayableLevel key={`${worldId}/${levelId}`} impressum={impressum} setImpressum={setImpressum} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/>} <PlayableLevel key={`${worldId}/${levelId}`} impressum={impressum} setImpressum={setImpressum} privacy={privacy} setPrivacy={setPrivacy} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/>}
{impressum ? <PrivacyPolicyPopup handleClose={closeImpressum} /> : null} {impressum ? <ImpressumPopup handleClose={closeImpressum} /> : null}
{privacy ? <PrivacyPolicyPopup handleClose={closePrivacy} /> : null}
{info ? <InfoPopup info={gameInfo.data?.info} handleClose={closeInfo}/> : null} {info ? <InfoPopup info={gameInfo.data?.info} handleClose={closeInfo}/> : null}
{preferencesPopup ? <PreferencesPopup handleClose={closePreferencesPopup} /> : null} {preferencesPopup ? <PreferencesPopup handleClose={closePreferencesPopup} /> : null}
</WorldLevelIdContext.Provider> </WorldLevelIdContext.Provider>
@ -212,7 +215,7 @@ function ExercisePanel({codeviewRef, visible=true}: {codeviewRef: React.MutableR
</div> </div>
} }
function PlayableLevel({impressum, setImpressum, toggleInfo, togglePreferencesPopup}) { function PlayableLevel({impressum, setImpressum, privacy, setPrivacy, toggleInfo, togglePreferencesPopup}) {
let { t } = useTranslation() let { t } = useTranslation()
const codeviewRef = useRef<HTMLDivElement>(null) const codeviewRef = useRef<HTMLDivElement>(null)
const gameId = React.useContext(GameIdContext) const gameId = React.useContext(GameIdContext)
@ -251,6 +254,7 @@ function PlayableLevel({impressum, setImpressum, toggleInfo, togglePreferencesPo
// impressum pop-up // impressum pop-up
function toggleImpressum() {setImpressum(!impressum)} function toggleImpressum() {setImpressum(!impressum)}
function togglePrivacy() {setPrivacy(!privacy)}
// When clicking on an inventory item, the inventory is overlayed by the item's doc. // When clicking on an inventory item, the inventory is overlayed by the item's doc.
// If this state is set to a pair `(name, type)` then the according doc will be open. // If this state is set to a pair `(name, type)` then the according doc will be open.
@ -419,8 +423,9 @@ function PlayableLevel({impressum, setImpressum, toggleInfo, togglePreferencesPo
isLoading={level.isLoading} isLoading={level.isLoading}
levelTitle={(mobile ? "" : t("Level")) + ` ${levelId} / ${gameInfo.data?.worldSize[worldId]}` + levelTitle={(mobile ? "" : t("Level")) + ` ${levelId} / ${gameInfo.data?.worldSize[worldId]}` +
(level?.data?.title && ` : ${t(level?.data?.title, {ns: gameId})}`)} (level?.data?.title && ` : ${t(level?.data?.title, {ns: gameId})}`)}
toggleImpressum={toggleImpressum} toggleImpressum={toggleImpressum}
toggleInfo={toggleInfo} togglePrivacy={togglePrivacy}
toggleInfo={toggleInfo}
togglePreferencesPopup={togglePreferencesPopup} togglePreferencesPopup={togglePreferencesPopup}
/> />
{mobile? {mobile?
@ -479,7 +484,7 @@ function IntroductionPanel({gameInfo}) {
export default Level export default Level
/** The site with the introduction text of a world */ /** The site with the introduction text of a world */
function Introduction({impressum, setImpressum, toggleInfo, togglePreferencesPopup}) { function Introduction({impressum, setImpressum, privacy, setPrivacy, toggleInfo, togglePreferencesPopup}) {
let { t } = useTranslation() let { t } = useTranslation()
const gameId = React.useContext(GameIdContext) const gameId = React.useContext(GameIdContext)
@ -497,9 +502,11 @@ function Introduction({impressum, setImpressum, toggleInfo, togglePreferencesPop
const toggleImpressum = () => { const toggleImpressum = () => {
setImpressum(!impressum) setImpressum(!impressum)
} }
const togglePrivacy = () => {
setPrivacy(!privacy)
}
return <> return <>
<LevelAppBar isLoading={gameInfo.isLoading} levelTitle={t("Introduction")} toggleImpressum={toggleImpressum} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/> <LevelAppBar isLoading={gameInfo.isLoading} levelTitle={t("Introduction")} toggleImpressum={toggleImpressum} togglePrivacy={togglePrivacy} toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/>
{gameInfo.isLoading ? {gameInfo.isLoading ?
<div className="app-content loading"><CircularProgress /></div> <div className="app-content loading"><CircularProgress /></div>
: mobile ? : mobile ?

@ -4,7 +4,7 @@
import * as React from 'react' import * as React from 'react'
import { Typography } from '@mui/material' import { Typography } from '@mui/material'
import Markdown from '../markdown' import Markdown from '../markdown'
import { useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { GameIdContext } from '../../app' import { GameIdContext } from '../../app'
/** Pop-up that is displaying the Game Info. /** Pop-up that is displaying the Game Info.
@ -22,6 +22,34 @@ export function InfoPopup ({info, handleClose}: {info: string, handleClose: () =
<div className="codicon codicon-close modal-close" onClick={handleClose}></div> <div className="codicon codicon-close modal-close" onClick={handleClose}></div>
<Typography variant="body1" component="div" className="welcome-text"> <Typography variant="body1" component="div" className="welcome-text">
<Markdown>{t(info, {ns: gameId})}</Markdown> <Markdown>{t(info, {ns: gameId})}</Markdown>
<hr />
<Trans>
<h2>Progress saving</h2>
<p>
The game stores your progress in your local browser storage. If you delete it, your progress will be lost!<br />
Warning: In most browsers, deleting cookies will also clear the local storage (or "local site data").
Make sure to download your game progress first!
</p>
<h2>Development</h2>
<p>The game engine has been created by <strong>Alexander Bentkamp</strong>, <strong>Jon Eugster</strong>.
On a prototype by <strong>Patrick Massot</strong>.
</p>
<p>
The source code of this Lean game engine
is <a href="https://github.com/leanprover-community/lean4game" target="_blank">available on Github</a>.
If you experience any problems, please
file an <a href="https://github.com/leanprover-community/lean4game/issues" target="_blank">Issue on Github</a> or
get directly in contact.
</p>
<h2>Funding</h2>
<p>
The game engine has been developed as part of the
project <a href="https://hhu-adam.github.io/" target="_blank">ADAM: Anticipating the Digital
Age of Mathematics</a> at
Heinrich-Heine-Universität Düsseldorf. It is funded by
the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.
</p>
</Trans>
</Typography> </Typography>
</div> </div>
</div> </div>

@ -4,6 +4,7 @@
import { faShield } from '@fortawesome/free-solid-svg-icons'; import { faShield } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as React from 'react' import * as React from 'react'
import { Trans, useTranslation } from 'react-i18next';
/** Pop-up that is displayed when opening the privacy policy. /** Pop-up that is displayed when opening the privacy policy.
* *
@ -13,49 +14,99 @@ import * as React from 'react'
* Note: Do not translate the Impressum! * Note: Do not translate the Impressum!
*/ */
export function PrivacyPolicyPopup ({handleClose}: {handleClose: () => void}) { export function PrivacyPolicyPopup ({handleClose}: {handleClose: () => void}) {
let {t, i18n} = useTranslation()
function content (lng = i18n.language) {
const tt = i18n.getFixedT(lng);
return <Trans t={tt} >
<h2>Privacy Policy</h2>
<p>
Our server collects metadata (such as IP address, browser, operating system)
and the data that the user enters into the editor. The data is used to
compute the Lean output and display it to the user. The information will be stored
as long as the user stays on our website and will be deleted immediately afterwards.
We keep logs to improve our software, but the contained data is anonymized.
</p>
<p>
We do not use cookies, but your game progress is stored in the browser
as site data. Your game progress is not saved on the server; if you delete
your browser storage, it is completely gone.
</p>
<p>Our server is located in Germany.</p>
<p>
<strong>Contact:</strong><br />
Marcus Zibrowius, Jon Eugster<br />
Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br />
Universitätsstr. 1<br />
40225 Düsseldorf<br />
Germany<br />
+49 211 81-14690<br />
<a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team">Contact Details</a>
</p>
</Trans>
}
return <div className="privacy-policy modal-wrapper">
<div className="modal-backdrop" onClick={handleClose} />
<div className="modal">
<div className="codicon codicon-close modal-close" onClick={handleClose}></div>
{i18n.language != 'en' && <>
<p><i>(English version below)</i></p>
{content()}
<hr />
</>}
{content('en')}
</div>
</div>
}
/** Pop-up that is displayed when opening the privacy policy.
*
* `handleClose` is the function to close it again because it's open/closed state is
* controlled by the containing element.
*
* Note: Do not translate the Impressum!
*/
export function ImpressumPopup ({handleClose}: {handleClose: () => void}) {
let {t, i18n} = useTranslation()
function content (lng = i18n.language) {
const tt = i18n.getFixedT(lng);
return <Trans t={tt} >
<h2>Impressum</h2>
<p>
<strong>Contact:</strong><br />
Marcus Zibrowius, Jon Eugster<br />
Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br />
Universitätsstr. 1<br />
40225 Düsseldorf<br />
Germany<br />
+49 211 81-14690<br />
<a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team">Contact Details</a>
</p>
<p>
<strong>Legal form:</strong><br />
The Heinrich Heine University Düsseldorf is a corporation under public law. It is legally represented by the Rector Prof. Dr. Anja Steinbeck. The responsible supervisory authority is the Ministry of Culture and Science of North Rhine-Westphalia, Völklinger Straße 49, 40221 Düsseldorf.
</p>
<p>
<strong>VAT identification number:</strong><br />
according to §27a Sales Tax Act<br />
DE 811222416
</p>
<p><a href="https://www.hhu.de/impressum" target="_blank">Impressum HHU</a></p>
</Trans>
}
return <div className="privacy-policy modal-wrapper"> return <div className="privacy-policy modal-wrapper">
<div className="modal-backdrop" onClick={handleClose} /> <div className="modal-backdrop" onClick={handleClose} />
<div className="modal"> <div className="modal">
<div className="codicon codicon-close modal-close" onClick={handleClose}></div> <div className="codicon codicon-close modal-close" onClick={handleClose}></div>
<h2>Privacy Policy &amp; Impressum</h2> {i18n.language != 'en' && <>
<p> <p><i>(English version below)</i></p>
Our server collects metadata (such as IP address, browser, operating system) {content()}
and the data that the user enters into the editor. The data is used to <hr />
compute the Lean output and display it to the user. The information will be stored </>}
as long as the user stays on our website and will be deleted immediately afterwards. {content('en')}
We keep logs to improve our software, but the contained data is anonymized. </div>
</p>
<p>
We do not use cookies, but your game progress is stored in the browser
as site data. Your game progress is not saved on the server; if you delete
your browser storage, it is completely gone.
</p>
<p>Our server is located in Germany.</p>
<p>
<strong>Contact information:</strong><br />
Alexander Bentkamp, Jon Eugster<br />
Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br />
Universitätsstr. 1<br />
40225 Düsseldorf<br />
Germany<br />
+49 211 81-12173<br />
<a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team/jon-eugster">Contact Details</a>
</p>
<h2>Development &amp; Funding</h2>
<p>
The source code of this Lean game engine
is <a href="https://github.com/leanprover-community/lean4game" target="_blank">available on Github</a>.
If you experience any problems, please
file an <a href="https://github.com/leanprover-community/lean4game/issues" target="_blank">Issue on Github</a> or
get directly in contact.
</p>
<p>
The game engine has been developed as part of the
project <a href="https://hhu-adam.github.io/" target="_blank">ADAM: Anticipating the Digital
Age of Mathematics</a> at
Heinrich-Heine-Universität Düsseldorf. It is funded by
the <i>Stiftung Innovation in der Hochschullehre</i> as part of project <i>Freiraum 2022</i>.
</p>
</div>
</div> </div>
} }

@ -14,7 +14,7 @@ import { PreferencesContext } from './infoview/context'
import { InventoryPanel } from './inventory' import { InventoryPanel } from './inventory'
import { ErasePopup } from './popup/erase' import { ErasePopup } from './popup/erase'
import { InfoPopup } from './popup/game_info' import { InfoPopup } from './popup/game_info'
import { PrivacyPolicyPopup } from './popup/privacy_policy' import { ImpressumPopup, PrivacyPolicyPopup } from './popup/privacy_policy'
import { RulesHelpPopup } from './popup/rules_help' import { RulesHelpPopup } from './popup/rules_help'
import { UploadPopup } from './popup/upload' import { UploadPopup } from './popup/upload'
import { PreferencesPopup} from "./popup/preferences" import { PreferencesPopup} from "./popup/preferences"
@ -86,6 +86,7 @@ function Welcome() {
// pop-ups // pop-ups
const [eraseMenu, setEraseMenu] = React.useState(false) const [eraseMenu, setEraseMenu] = React.useState(false)
const [impressum, setImpressum] = React.useState(false) const [impressum, setImpressum] = React.useState(false)
const [privacy, setPrivacy] = React.useState(false)
const [info, setInfo] = React.useState(false) const [info, setInfo] = React.useState(false)
const [rulesHelp, setRulesHelp] = React.useState(false) const [rulesHelp, setRulesHelp] = React.useState(false)
const [uploadMenu, setUploadMenu] = React.useState(false) const [uploadMenu, setUploadMenu] = React.useState(false)
@ -93,12 +94,14 @@ function Welcome() {
function closeEraseMenu() {setEraseMenu(false)} function closeEraseMenu() {setEraseMenu(false)}
function closeImpressum() {setImpressum(false)} function closeImpressum() {setImpressum(false)}
function closePrivacy() {setPrivacy(false)}
function closeInfo() {setInfo(false)} function closeInfo() {setInfo(false)}
function closeRulesHelp() {setRulesHelp(false)} function closeRulesHelp() {setRulesHelp(false)}
function closeUploadMenu() {setUploadMenu(false)} function closeUploadMenu() {setUploadMenu(false)}
function closePreferencesPopup() {setPreferencesPopup(false)} function closePreferencesPopup() {setPreferencesPopup(false)}
function toggleEraseMenu() {setEraseMenu(!eraseMenu)} function toggleEraseMenu() {setEraseMenu(!eraseMenu)}
function toggleImpressum() {setImpressum(!impressum)} function toggleImpressum() {setImpressum(!impressum)}
function togglePrivacy() {setPrivacy(!privacy)}
function toggleInfo() {setInfo(!info)} function toggleInfo() {setInfo(!info)}
function toggleUploadMenu() {setUploadMenu(!uploadMenu)} function toggleUploadMenu() {setUploadMenu(!uploadMenu)}
function togglePreferencesPopup() {setPreferencesPopup(!preferencesPopup)} function togglePreferencesPopup() {setPreferencesPopup(!preferencesPopup)}
@ -115,7 +118,7 @@ function Welcome() {
<CircularProgress /> <CircularProgress />
</Box> </Box>
: <> : <>
<WelcomeAppBar pageNumber={pageNumber} setPageNumber={setPageNumber} gameInfo={gameInfo.data} toggleImpressum={toggleImpressum} <WelcomeAppBar pageNumber={pageNumber} setPageNumber={setPageNumber} gameInfo={gameInfo.data} toggleImpressum={toggleImpressum} togglePrivacy={togglePrivacy}
toggleEraseMenu={toggleEraseMenu} toggleUploadMenu={toggleUploadMenu} toggleEraseMenu={toggleEraseMenu} toggleUploadMenu={toggleUploadMenu}
toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/> toggleInfo={toggleInfo} togglePreferencesPopup={togglePreferencesPopup}/>
<div className="app-content"> <div className="app-content">
@ -139,7 +142,8 @@ function Welcome() {
</Split> </Split>
} }
</div> </div>
{impressum ? <PrivacyPolicyPopup handleClose={closeImpressum} /> : null} {impressum ? <ImpressumPopup handleClose={closeImpressum} /> : null}
{privacy ? <PrivacyPolicyPopup handleClose={closePrivacy} /> : null}
{rulesHelp ? <RulesHelpPopup handleClose={closeRulesHelp} /> : null} {rulesHelp ? <RulesHelpPopup handleClose={closeRulesHelp} /> : null}
{eraseMenu? <ErasePopup handleClose={closeEraseMenu}/> : null} {eraseMenu? <ErasePopup handleClose={closeEraseMenu}/> : null}
{uploadMenu? <UploadPopup handleClose={closeUploadMenu}/> : null} {uploadMenu? <UploadPopup handleClose={closeUploadMenu}/> : null}

@ -145,3 +145,9 @@ em {
.privacy-policy { .privacy-policy {
z-index: 10; z-index: 10;
} }
.modal hr {
margin-top: 3rem;
margin-bottom: 3rem;
border-color: var(--vscode-breadcrumb-foreground);
}

@ -23,13 +23,19 @@
</p> </p>
<p> <p>
<strong>Impressum:</strong><br /> <strong>Impressum:</strong><br />
Jon Eugster<br /> Marcus Zibrowius, Jon Eugster<br />
Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br /> Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br />
Universitätsstr. 1<br /> Universitätsstr. 1<br />
40225 Düsseldorf<br /> 40225 Düsseldorf<br />
Germany<br /> Germany<br />
+49 211 81-12173<br /> +49 211 81-14690<br />
<a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team/jon-eugster">Contact Details</a> <a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team">Contact Details</a>
</p>
<p>
<strong>Datenschutzerklärung:</strong><br />
Without JavaScript this website cannot be used and therefore no personal data is collected
or stored.<br />
Our Server is located in Germany.<br />
</p> </p>
</div> </div>
</noscript> </noscript>

Loading…
Cancel
Save