From 2bc025f1b5ded21a3ec36ec19661f5b45abb78fd Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Mon, 29 Apr 2019 07:55:11 +0200 Subject: [PATCH] 1.0 --- src/app/app-routing.module.ts | 70 ++- src/app/app.module.ts | 21 +- src/app/article/article.component.ts | 72 ++- src/app/fwlink-mapper.ts | 35 ++ src/app/gui/big-logo/big-logo.component.scss | 2 +- src/app/gui/navbar/navbar.component.ts | 19 +- src/app/services/document-fetch.service.ts | 19 +- src/assets/midi23d/delta.svg | 463 ++++++++++++++++++ src/assets/midi23d/midi-gui.png | Bin 0 -> 31202 bytes src/documents/WarpPI.en.md | 3 + src/documents/WarpPi.it.md | 3 + src/documents/contacts.en.md | 15 + src/documents/contacts.it.md | 15 + .../discontinued/gatecraft-accounts.en.md | 5 + src/documents/discontinued/gatepack.en.md | 5 + src/documents/discontinued/gatepack.it.md | 5 + .../discontinued/warpgate-apps.en.md | 5 + .../discontinued/warpgate-apps.it.md | 5 + src/documents/index.en.md | 17 +- src/documents/index.it.md | 17 +- src/documents/license.en.md | 392 +++++++++++++++ src/documents/software.en.md | 6 + src/documents/software.it.md | 6 + src/documents/software/midi23d.en.md | 54 +- src/index.html | 2 +- src/manifest.json | 2 +- src/styles-variables.scss | 3 +- src/styles.scss | 15 +- 28 files changed, 1211 insertions(+), 65 deletions(-) create mode 100644 src/app/fwlink-mapper.ts create mode 100644 src/assets/midi23d/delta.svg create mode 100644 src/assets/midi23d/midi-gui.png create mode 100644 src/documents/WarpPI.en.md create mode 100644 src/documents/WarpPi.it.md create mode 100644 src/documents/contacts.en.md create mode 100644 src/documents/contacts.it.md create mode 100644 src/documents/discontinued/gatecraft-accounts.en.md create mode 100644 src/documents/discontinued/gatepack.en.md create mode 100644 src/documents/discontinued/gatepack.it.md create mode 100644 src/documents/discontinued/warpgate-apps.en.md create mode 100644 src/documents/discontinued/warpgate-apps.it.md create mode 100644 src/documents/license.en.md create mode 100644 src/documents/software.en.md create mode 100644 src/documents/software.it.md diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 082531a..215af92 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,23 +1,87 @@ import { NgModule } from "@angular/core"; -import { Routes, RouterModule } from "@angular/router"; +import { Routes, RouterModule, UrlSegment, UrlMatchResult } from "@angular/router"; import { ArticleComponent } from "./article/article.component"; import { RouterEmptyComponent } from "./gui/router-empty/router-empty.component"; +import { NavigationLink } from "./symbols/NavigationLink"; const routes: Routes = [ { path: "", - component: ArticleComponent + component: ArticleComponent, + data: { + resolveUrlPaths: false + }, }, { - path: "page", + matcher: pageMatcher, component: RouterEmptyComponent, children: [{ path: "**", + data: { + resolveUrlPaths: false + }, component: ArticleComponent }] + }, + { + matcher: fwlinkMatcher, + component: RouterEmptyComponent, + children: [{ + path: "**", + data: { + resolveUrlPaths: true + }, + component: ArticleComponent + }] + }, + { + path: "**", + data: { + notFound: true + }, + component: ArticleComponent } ]; +export const navigationLinks: NavigationLink[] = [ + { + text: "WarpPI", + address: "/page/WarpPI" + }, + { + text: "Midi23D", + address: "/page/software/Midi23D" + }, + { + text: "Contacts", + address: "/page/contacts" + }, + { + text: "Github ↗", + address: "https://github.com/Cavallium", + external: true, + newtab: true + }, +]; + +export function pageMatcher(url: UrlSegment[]): UrlMatchResult { + if (url.length > 1) { + if (url[0].path === "page") { + return { consumed: [url[0]] }; + } + } + return null; +} + +export function fwlinkMatcher(url: UrlSegment[]): UrlMatchResult { + if (url.length === 1) { + if (url[0].path === "fwlink.php") { + return { consumed: url }; + } + } + return null; +} + @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d0f9baf..1451e6e 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,9 +10,10 @@ import { ArticleComponent } from "./article/article.component"; import { RouterEmptyComponent } from "./gui/router-empty/router-empty.component"; import {HttpClientModule} from "@angular/common/http"; import { MarkdownModule, MarkedOptions, MarkedRenderer, MarkdownComponent } from "ngx-markdown"; -import { BigLogoComponent } from './gui/big-logo/big-logo.component'; -import { ServiceWorkerModule } from '@angular/service-worker'; -import { environment } from '../environments/environment'; +import { BigLogoComponent } from "./gui/big-logo/big-logo.component"; +import { ServiceWorkerModule } from "@angular/service-worker"; +import { environment } from "../environments/environment"; +import { isString } from "util"; @NgModule({ declarations: [ @@ -48,7 +49,19 @@ export function markedOptionsFactory(): MarkedOptions { return "

" + text + "

"; }; renderer.link = (href: string, title: string, text: string) => { - return "" + text + ""; + let result = ""; + return result; + }; + + renderer.image = (href: string, title: string, text: string) => { + return "\"""; }; return { diff --git a/src/app/article/article.component.ts b/src/app/article/article.component.ts index b4cd586..baa5116 100644 --- a/src/app/article/article.component.ts +++ b/src/app/article/article.component.ts @@ -1,10 +1,13 @@ -import { Component, OnInit, OnDestroy } from "@angular/core"; -import { ActivatedRoute, UrlSegment } from "@angular/router"; +import { Component, OnInit, OnDestroy, HostListener } from "@angular/core"; +import { ActivatedRoute, UrlSegment, Params, Router } from "@angular/router"; import { map } from "rxjs/operators"; import { DocumentFetchService } from "../services/document-fetch.service"; import { DocumentData } from "../symbols/DocumentData"; import { MarkdownService } from "ngx-markdown"; import { CurrentDocumentService } from "../services/current-document.service"; +import { combineLatest } from "rxjs"; +import { fwlinkMapper } from "../fwlink-mapper"; +import { isObject, isString } from "util"; @Component({ selector: "app-article", @@ -19,17 +22,53 @@ export class ArticleComponent implements OnInit, OnDestroy { private activatedRoute: ActivatedRoute, private documentFetcher: DocumentFetchService, private markdownService: MarkdownService, - private currentDocumentService: CurrentDocumentService - ) { } + private currentDocumentService: CurrentDocumentService, + private router: Router + ) { } ngOnInit() { - this.activatedRoute.url - .pipe(map((urlSegments: UrlSegment[]) => urlSegments.map(urlSegment => urlSegment.path).join("/"))) - .subscribe(async (url: string) => { - const docData: DocumentData = await this.documentFetcher.fetch(url); - this.documentData = docData; - this.currentDocumentService.setCurrentDocument(docData); - }); + const urlEvent = this.activatedRoute.url + .pipe(map((urlSegments: UrlSegment[]) => urlSegments.map(urlSegment => urlSegment.path).join("/"))); + + const dataEvent = this.activatedRoute.data + .pipe(map(data => { + return { + resolveUrlPaths: data.resolveUrlPaths === true, + notFound: data.notFound === true + }; + })); + + const queryEvent = this.activatedRoute.queryParams + .pipe(map((params: Params) => isString(params.page) ? params.page : params.p)); + + combineLatest(urlEvent, dataEvent, queryEvent) + .pipe(map((combined) => { + return { + url: combined[0], + queryPage: combined[2], + resolveUrlPaths: combined[1].resolveUrlPaths, + notFound: combined[1].notFound, + }; + })) + .subscribe(async (data) => { + let resolvedUrl: string; + if (!data.notFound) { + if (data.resolveUrlPaths) { + resolvedUrl = fwlinkMapper(data.queryPage); + } else { + if ((isString(data.url) && data.url.length === 0 || !isString(data.url)) && isString(data.queryPage) && data.queryPage.length > 0) { + resolvedUrl = data.queryPage; + } else { + resolvedUrl = data.url; + } + } + } else { + resolvedUrl = "404"; + } + const docData: DocumentData = await this.documentFetcher.fetch(resolvedUrl); + this.documentData = docData; + this.currentDocumentService.setCurrentDocument(docData); + }); } @@ -37,4 +76,15 @@ export class ArticleComponent implements OnInit, OnDestroy { this.currentDocumentService.setCurrentDocument(null); } + @HostListener("click", ["$event"]) + public onClick(e: Event) { + if (isObject(e.target)) { + const target = e.target as HTMLLinkElement; + if (isString(target.dataset.routerlink)) { + e.preventDefault(); + this.router.navigateByUrl(target.dataset.routerlink); + } + } + } + } diff --git a/src/app/fwlink-mapper.ts b/src/app/fwlink-mapper.ts new file mode 100644 index 0000000..7e75eee --- /dev/null +++ b/src/app/fwlink-mapper.ts @@ -0,0 +1,35 @@ +import { isString } from "util"; + +const redirects = { + home: "index", + homepage: "index", + "home page": "index", + license: "license", + software: "software", + "segnalazione app": "contacts", + "Gatecraft Apps": "discontinued/warpgate-apps", + "WarpGate Apps": "discontinued/warpgate-apps", + "WarpGate Store": "discontinued/warpgate-apps", + ServerStore: "discontinued/warpgate-apps", + feedback: "contacts", + login: "discontinued/gatecraft-accounts", + account: "discontinued/gatecraft-accounts", + modpack: "discontinued/gatepack", + gatepack: "discontinued/gatepack", + G2CardboardFix: "android/g2cardboard", + warppi: "WarpPI", + midi23D: "software/Midi23D", + mid23D: "software/Midi23D", + "elettronica/WarpPi": "WarpPI", + "elettronica/midi23D": "software/Midi23D", + "modpack/guida": "discontinued/gatepack", + "modpack/base/mondi": "discontinued/gatepack", +}; + +export function fwlinkMapper(url: string): string { + if (isString(redirects[url])) { + return redirects[url]; + } else { + return url; + } +} diff --git a/src/app/gui/big-logo/big-logo.component.scss b/src/app/gui/big-logo/big-logo.component.scss index 5ade9cb..13dde7e 100644 --- a/src/app/gui/big-logo/big-logo.component.scss +++ b/src/app/gui/big-logo/big-logo.component.scss @@ -1,7 +1,7 @@ @import "../../../styles-variables.scss"; :host { display: block; - background-color: $color-main; + background: linear-gradient(0deg, $color-main, $color-main-darker); color: white; text-align: center; position: relative; diff --git a/src/app/gui/navbar/navbar.component.ts b/src/app/gui/navbar/navbar.component.ts index 2057291..66f71eb 100644 --- a/src/app/gui/navbar/navbar.component.ts +++ b/src/app/gui/navbar/navbar.component.ts @@ -3,6 +3,7 @@ import { NavigationLink } from "src/app/symbols/NavigationLink"; import { ActivatedRoute, UrlSegment } from "@angular/router"; import { map } from "rxjs/operators"; import { CurrentDocumentService } from "src/app/services/current-document.service"; +import { navigationLinks } from "src/app/app-routing.module"; @Component({ selector: "app-navbar", @@ -11,23 +12,7 @@ import { CurrentDocumentService } from "src/app/services/current-document.servic }) export class NavbarComponent implements OnInit, AfterViewInit { - public navigationLinks: NavigationLink[] = [ - { - text: "Midi23D", - address: "/page/Midi23D" - }, - { - text: "WarpPI Calculator", - address: "/page/WarpPI", - newtab: false - }, - { - text: "Github", - address: "https://github.com/Cavallium/WarpPI", - external: true, - newtab: true - }, - ]; + public navigationLinks: NavigationLink[] = navigationLinks; stickedOnTop = false; overflowLogo = false; overflowMax = false; diff --git a/src/app/services/document-fetch.service.ts b/src/app/services/document-fetch.service.ts index 59dd570..52f5c3c 100644 --- a/src/app/services/document-fetch.service.ts +++ b/src/app/services/document-fetch.service.ts @@ -2,6 +2,7 @@ import { Injectable } from "@angular/core"; import { DocumentData } from "../symbols/DocumentData"; import { HttpClient } from "@angular/common/http"; import { take } from "rxjs/operators"; +import { fwlinkMapper } from "../fwlink-mapper"; @Injectable({ providedIn: "root" @@ -22,11 +23,12 @@ export class DocumentFetchService { public async fetch(unsafeId: string): Promise { const encodedId = this.encodeId(unsafeId); + try { - return await this.fetchWithLanguage(encodedId, this.language); + return await this.fetchInternal(encodedId); } catch (e) { try { - return await this.fetchWithLanguage(encodedId, "en"); + return await this.fetchInternal(this.encodeId(fwlinkMapper(encodedId))); } catch (e) { return { found: false, @@ -37,8 +39,15 @@ export class DocumentFetchService { } } - private async fetchWithLanguage(unsafeId: string, language: string): Promise { - const encodedId = this.encodeId(unsafeId); + private async fetchInternal(encodedId: string): Promise { + try { + return await this.fetchWithLanguage(encodedId, this.language); + } catch (e) { + return await this.fetchWithLanguage(encodedId, "en"); + } + } + + private async fetchWithLanguage(encodedId: string, language: string): Promise { const response: string = await this.http.get("/documents/" + encodedId + "." + language + ".md", { responseType: "text" }) .pipe(take(1)).toPromise(); return { @@ -61,7 +70,7 @@ export class DocumentFetchService { } private encodeId(id: string): string { - const encoded = id.split("/").map(encodeURIComponent).filter((part) => part.length > 0 && !/[^a-zA-Z0-9_-àùéèì]/.test(part)).join("/"); + const encoded = id.split("/").map(encodeURIComponent).filter((part) => part.length > 0 && !/[^a-zA-Z0-9_\-àùéèì]/.test(part)).join("/"); if (encoded.length > 0) { return encoded; } else { diff --git a/src/assets/midi23d/delta.svg b/src/assets/midi23d/delta.svg new file mode 100644 index 0000000..835f270 --- /dev/null +++ b/src/assets/midi23d/delta.svg @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known values:time = note timesx = motor X speed (note)Unknown values:stot = total speed∆px = motor X position + + diff --git a/src/assets/midi23d/midi-gui.png b/src/assets/midi23d/midi-gui.png new file mode 100644 index 0000000000000000000000000000000000000000..52c6104a83d78531f11f5be403019f41ef98fa64 GIT binary patch literal 31202 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 WOqu&J73j-+?6$JztujT6u>S|s=r{EM literal 0 HcmV?d00001 diff --git a/src/documents/WarpPI.en.md b/src/documents/WarpPI.en.md new file mode 100644 index 0000000..7affc0b --- /dev/null +++ b/src/documents/WarpPI.en.md @@ -0,0 +1,3 @@ +# WarpPI Calculator + +https://github.com/Cavallium/WarpPI diff --git a/src/documents/WarpPi.it.md b/src/documents/WarpPi.it.md new file mode 100644 index 0000000..a44310a --- /dev/null +++ b/src/documents/WarpPi.it.md @@ -0,0 +1,3 @@ +# Calcolatrice WarpPI + +https://github.com/Cavallium/WarpPI diff --git a/src/documents/contacts.en.md b/src/documents/contacts.en.md new file mode 100644 index 0000000..5ef36a8 --- /dev/null +++ b/src/documents/contacts.en.md @@ -0,0 +1,15 @@ +# Contacts + +## Andrea Cavalli (Cavallium) + +Enthusiast programmer. + +[**My LinkedIn account**](https://www.linkedin.com/in/cavallium/?trk=profile-badge) + +**e-mail**: nospam@warp.ovh + +**Location**: Milan, Italy + +**Telegram**: @Cavaiiium + +**Twitter**: [@Cavallium](https://twitter.com/Cavallium) \ No newline at end of file diff --git a/src/documents/contacts.it.md b/src/documents/contacts.it.md new file mode 100644 index 0000000..c68d304 --- /dev/null +++ b/src/documents/contacts.it.md @@ -0,0 +1,15 @@ +# Contatti + +## Andrea Cavalli (Cavallium) + +Programmatore e Web developer per passione + +[**Il mio account LinkedIn**](https://www.linkedin.com/in/cavallium/?trk=profile-badge) + +**e-mail**: nospam@warp.ovh + +**Posizione**: Milano, Italia + +**Telegram**: @Cavaiiium + +**Twitter**: [@Cavallium](https://twitter.com/Cavallium) \ No newline at end of file diff --git a/src/documents/discontinued/gatecraft-accounts.en.md b/src/documents/discontinued/gatecraft-accounts.en.md new file mode 100644 index 0000000..ad5d4cd --- /dev/null +++ b/src/documents/discontinued/gatecraft-accounts.en.md @@ -0,0 +1,5 @@ +# Gatecraft account + +## This service is no longer available + +For more information contact me: *nospam@warp.ovh* diff --git a/src/documents/discontinued/gatepack.en.md b/src/documents/discontinued/gatepack.en.md new file mode 100644 index 0000000..699d6ff --- /dev/null +++ b/src/documents/discontinued/gatepack.en.md @@ -0,0 +1,5 @@ +# GatePack + +## This service is no longer available + +For more information contact me: *nospam@warp.ovh* diff --git a/src/documents/discontinued/gatepack.it.md b/src/documents/discontinued/gatepack.it.md new file mode 100644 index 0000000..f1cbee1 --- /dev/null +++ b/src/documents/discontinued/gatepack.it.md @@ -0,0 +1,5 @@ +# GatePack + +## Questo servizio non è più disponibile + +Per maggiori informazioni contatta: *nospam@warp.ovh* diff --git a/src/documents/discontinued/warpgate-apps.en.md b/src/documents/discontinued/warpgate-apps.en.md new file mode 100644 index 0000000..32e4b2e --- /dev/null +++ b/src/documents/discontinued/warpgate-apps.en.md @@ -0,0 +1,5 @@ +# WarpGate Apps + +## This service is no longer available + +For more information contact me: *nospam@warp.ovh* diff --git a/src/documents/discontinued/warpgate-apps.it.md b/src/documents/discontinued/warpgate-apps.it.md new file mode 100644 index 0000000..e122944 --- /dev/null +++ b/src/documents/discontinued/warpgate-apps.it.md @@ -0,0 +1,5 @@ +# WarpGate Apps + +## Questo servizio non è più disponibile + +Per maggiori informazioni contatta: *nospam@warp.ovh* diff --git a/src/documents/index.en.md b/src/documents/index.en.md index 9b633dc..2c11d7e 100644 --- a/src/documents/index.en.md +++ b/src/documents/index.en.md @@ -2,19 +2,22 @@ **Cavallium.it** è il mio sito personale, in cui pubblico varie pagine riguardanti le mie creazioni nell'ambito informatico. -Dato che mi piace creare siti web, Cavallium.it è stato fatto interamente da me nel 2019 utilizzando Angular 9. +Attualmente sviluppo sia in ambito desktop che web. -Oltre alle pagine web mi piace creare applicazioni, sia web che desktop. Nel 2016 ho iniziato ad avvicinarmi anche all'elettronica, iniziando a progettare la calcolatrice WarpPI. -Negli ultimi tre anni mi sono focalizzato sullo sviluppo di **applicazioni web** e **progressive web apps** usando il framework **Angular** insieme a **RxJs** e **Firebase**, oltre a sviluppare software in **Java**. La maggior parte delle web app che ho sviluppato non possono essere mostrate pubblicamente qui, nonostante ciò le altre web app che ho sviluppato sono: +Negli ultimi tre anni mi sono focalizzato sullo sviluppo di **applicazioni web** e **progressive web apps** usando il framework **Angular** insieme a **RxJs** e **Firebase**, oltre a sviluppare software desktop in **Java**.\ +La maggior parte delle web app che ho sviluppato sono commissioni per privati, pertanto non possono essere mostrate pubblicamente qui, mentre i siti pubblici che ho creato sono i seguenti: + +* [Cavallium.it](https://cavallium.it) * [ExtraDrone.it](https://extradrone.it) -Il menù sottostante contiene solo i miei ultimi progetti più rilevanti (altrimenti avrei dovuto fare una lista infinitamente lunga piena di stupide prove e progetti sperimentali). +Il menù sottostante contiene i miei progetti più rilevanti. Dacci un'occhiata 😉 * [WarpPi Calculator](/page/WarpPI) -* [Midi23D](/page/Midi23D) -* [OpenRC Formula 1 Car](https://www.youtube.com/watch?v=EF921CLhXQg&vl=it&ab_channel=AndreaCavalli) +* [Midi23D](/page/software/Midi23D) -Oltre a questo sito possiedo un [server locale al seguente indirizzo](https://rk3328.cc) \ No newline at end of file +Possiedo anche un piccolo [server locale](https://local.cavallium.it) in cui pubblico alcuni esperimenti. + +[License](/page/license) diff --git a/src/documents/index.it.md b/src/documents/index.it.md index 9b633dc..28831a4 100644 --- a/src/documents/index.it.md +++ b/src/documents/index.it.md @@ -2,19 +2,22 @@ **Cavallium.it** è il mio sito personale, in cui pubblico varie pagine riguardanti le mie creazioni nell'ambito informatico. -Dato che mi piace creare siti web, Cavallium.it è stato fatto interamente da me nel 2019 utilizzando Angular 9. +Attualmente sviluppo sia in ambito desktop che web. -Oltre alle pagine web mi piace creare applicazioni, sia web che desktop. Nel 2016 ho iniziato ad avvicinarmi anche all'elettronica, iniziando a progettare la calcolatrice WarpPI. -Negli ultimi tre anni mi sono focalizzato sullo sviluppo di **applicazioni web** e **progressive web apps** usando il framework **Angular** insieme a **RxJs** e **Firebase**, oltre a sviluppare software in **Java**. La maggior parte delle web app che ho sviluppato non possono essere mostrate pubblicamente qui, nonostante ciò le altre web app che ho sviluppato sono: +Negli ultimi tre anni mi sono focalizzato sullo sviluppo di **applicazioni web** e **progressive web apps** usando il framework **Angular** insieme a **RxJs** e **Firebase**, oltre a sviluppare software desktop in **Java**.\ +La maggior parte delle web app che ho sviluppato sono commissioni per privati, pertanto non possono essere mostrate pubblicamente qui, mentre i siti pubblici che ho creato sono i seguenti: + +* [Cavallium.it](https://cavallium.it) * [ExtraDrone.it](https://extradrone.it) -Il menù sottostante contiene solo i miei ultimi progetti più rilevanti (altrimenti avrei dovuto fare una lista infinitamente lunga piena di stupide prove e progetti sperimentali). +Il menù sottostante contiene i miei progetti più rilevanti. Dacci un'occhiata 😉 * [WarpPi Calculator](/page/WarpPI) -* [Midi23D](/page/Midi23D) -* [OpenRC Formula 1 Car](https://www.youtube.com/watch?v=EF921CLhXQg&vl=it&ab_channel=AndreaCavalli) +* [Midi23D](/page/software/Midi23D) -Oltre a questo sito possiedo un [server locale al seguente indirizzo](https://rk3328.cc) \ No newline at end of file +Possiedo anche un piccolo [server locale](https://local.cavallium.it) in cui pubblico alcuni esperimenti. + +[Licenza](/page/license) \ No newline at end of file diff --git a/src/documents/license.en.md b/src/documents/license.en.md new file mode 100644 index 0000000..816c9fb --- /dev/null +++ b/src/documents/license.en.md @@ -0,0 +1,392 @@ +# License + +## Attribution-NoDerivatives 4.0 International + +``` +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + + +======================================================================= + +Creative Commons Attribution-NoDerivatives 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NoDerivatives 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + c. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + d. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + e. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + f. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + g. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + h. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + i. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + j. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce and reproduce, but not Share, Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material, You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + For the avoidance of doubt, You do not have permission under + this Public License to Share Adapted Material. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database, provided You do not Share + Adapted Material; + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. +``` diff --git a/src/documents/software.en.md b/src/documents/software.en.md new file mode 100644 index 0000000..d9f058c --- /dev/null +++ b/src/documents/software.en.md @@ -0,0 +1,6 @@ +# Software + +Here's my software: + +* [WarpPI Calculator](/page/WarpPI), an experimental calculator +* [Midi23D](/page/software/Midi23D), a tool to convert .midi files into playable GCODE files for cartesian printers diff --git a/src/documents/software.it.md b/src/documents/software.it.md new file mode 100644 index 0000000..d00c88d --- /dev/null +++ b/src/documents/software.it.md @@ -0,0 +1,6 @@ +# Software + +I miei software: + +* [Calcolatrice WarpPI](/page/WarpPI), una calcolatrice Algebrica sperimentale +* [Midi23D](/page/software/Midi23D), un programma per convertire i file .midi in codice GCODE adatto a quasi tutte le stampanti 3D cartesiane diff --git a/src/documents/software/midi23d.en.md b/src/documents/software/midi23d.en.md index 82a2752..1ddca06 100644 --- a/src/documents/software/midi23d.en.md +++ b/src/documents/software/midi23d.en.md @@ -1,3 +1,55 @@ # Midi23D -This is a test page \ No newline at end of file +## Summary + +**Midi23D** is a tool made in Java that converts every note of a .midi music into GCODE instructions to send directly to a 3D printer. + +![gui](/assets/midi23d/midi-gui.png) + +## How it works + +Every 3D printer has 3 or more particular motors, called **stepper motors**. Despite of the regular DC motors their angular speed and rotation be controlled very precisely. + +Sending an impulse to that motors, in addition to result in a rotation, it will produce a sound, that it can be modulated by changing it. + +With the GCODE you can tell to the 3D printer extruder to go in a position with a determined speed. + +Setting the right speed for each motor by sending to the printer only the position and the total speed seems difficult, but it's quite easy. +You must use this formula: + +![explanation](/assets/midi23d/delta.svg) + +In this way you can control simultaneously one note for each motor. + +## Usage + +First of all, download **_Midi23D.jar_** + +[Midi23D.jar](http://gdb.altervista.org/downloads/Midi23D.jar) + +Run the program by clicking on it if you have a GUI, or by executing it into your terminal: +`java -jar Midi23D.jar ` +_(Motor-test is a boolean (true/false) parameter that if it's true it plays the same notes on all the motors. It helps when you try to accord each motor speed)._ + +Insert the parameters that asks to you. + +Drag and drop the generated file into Repetier Host or your program that controls your printer. + +Enjoy + +## Samples + +* [Pokémon center.mid](http://gdb.altervista.org/downloads/midi/pokemon_center.mid) +* [Pokémon Red route 1.mid](http://gdb.altervista.org/downloads/midi/route_1.mid) +* [Pokémon Red route 24.mid](http://gdb.altervista.org/downloads/midi/route_24.mid) +* [Harry Potter theme.mid](http://gdb.altervista.org/downloads/midi/HarryPotter.mid) +* [Super Mario Bros theme.mid](http://gdb.altervista.org/downloads/midi/super_mario_bros.mid) +* [Castlevania Legends Boss.mid](http://gdb.altervista.org/downloads/midi/CVL_Boss.mid) +* [Harry Potter for gameboy Main menu.mid](http://gdb.altervista.org/downloads/midi/Harry_Potter_game_main_menu.mid) +* [Wild Pokémon encounter.mid](http://gdb.altervista.org/downloads/midi/wild_pokemon_battle.mid) + +## Videos + +
+ +
\ No newline at end of file diff --git a/src/index.html b/src/index.html index b0a596f..844d5e9 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,7 @@ - + diff --git a/src/manifest.json b/src/manifest.json index 8f63eeb..a1396b9 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "name": "Cavallium.it", "short_name": "Cavallium.it", - "theme_color": "#1976d2", + "theme_color": "#2c41b9", "background_color": "#ffffff", "display": "minimal-ui", "scope": "/", diff --git a/src/styles-variables.scss b/src/styles-variables.scss index 0fc5ee0..17d9012 100644 --- a/src/styles-variables.scss +++ b/src/styles-variables.scss @@ -1,2 +1,3 @@ -$color-main: #3F51B5; +$color-main: #2c41b9; +$color-main-darker: #122792; $mobile-mode-size: 425px; \ No newline at end of file diff --git a/src/styles.scss b/src/styles.scss index c6cdaeb..4e4fe7c 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -20,10 +20,13 @@ strong, b, h1, h2, h3, h4, h5, h6, th { .document-style-warning{ color: red; } - -@media only screen, (any-pointer: fine) { - .article-link { - min-height: 48px; - display: inline-block; - } +.article-image { + max-width: 100%; } + +@media only screen and (any-pointer: coarse) { + .article-link { + line-height: 48px; + display: inline-block; + } +} \ No newline at end of file