Compare commits

..
10 Commits
20 changed files with 1346 additions and 11563 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
10.24.1
+56
View File
@@ -0,0 +1,56 @@
# Agent Guidelines for NLS Guilloche Generator
**IMPORTANT**: This is an archived Angular 6 project. We maintain it for running purposes only - no development, upgrades, or new features. Never run npm commands directly; always use the Makefile/nix shell wrapper.
## Build/Lint/Test Commands
- **Build app**: `npm run build`
- **Build library**: `npm run build:library`
- **Start dev server**: `npm start`
- **Lint**: `npm run lint`
- **Run all tests**: `npm run test`
- **Run single test**: `ng test --include="**/specific-test.spec.ts"`
- **E2E tests**: `npm run e2e`
## Code Style Guidelines
### Formatting
- 2-space indentation
- Single quotes for strings
- Semicolons always
- Max line length: 140 characters
- No trailing whitespace
- Insert final newline in files
### TypeScript/Angular
- Target: ES5
- Use `const` instead of `let` when possible
- Arrow return shorthand
- Interface over type literal
- No unused expressions
- No console.log (except debug/info/time/timeEnd/trace)
- Component class suffix required
- Import spacing required
### Naming Conventions
- **Components**: PascalCase + `Component` suffix (e.g., `AppComponent`)
- **Services**: PascalCase + `Service` suffix (e.g., `NlsMathService`)
- **Models**: PascalCase + `.model` suffix (e.g., `point.model.ts`)
- **Files**: kebab-case for components, camelCase for services/models
- **Properties/Methods**: camelCase
### Member Ordering
1. Static fields
2. Instance fields
3. Static methods
4. Instance methods
### Imports
- Angular imports first
- Third-party imports second
- Local imports last
- Use relative imports (`./` or `../`)
### Error Handling
- Follow standard TypeScript practices
- Use appropriate Angular error handling patterns
+12
View File
@@ -0,0 +1,12 @@
.PHONY: start build help
start:
NIXPKGS_ALLOW_INSECURE=1 nix-shell --run "npm start"
build:
NIXPKGS_ALLOW_INSECURE=1 nix-shell --run "npm run build"
help:
@echo "Available commands:"
@echo " start - Start the development server"
@echo " build - Build the project for production"
+15 -4
View File
@@ -15,10 +15,21 @@
--- ---
## Rquirements ## Requirements
- Node.js - Node.js 10.24.1 (insecure EOL version, provided without warranty)
- Angular CLI - Angular CLI
- Nix (for reproducible development environment)
## Development Setup
This project uses Nix for a reproducible development environment.
1. Enter the Nix shell: `nix-shell`
2. Install dependencies: `npm install`
3. Start development: `make start` or `npm run start`
**Disclaimer:** This software is provided without any warranty. Use at your own risk.
## NPM Scripts ## NPM Scripts
@@ -30,9 +41,9 @@
## Development server ## Development server
Download dependencies with `npm i` or `yarn`. After entering the Nix shell, download dependencies with `npm install`.
Run `npm run start` for a dev server. Browser opens and navigates automatically to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. Run `make start` or `npm run start` for a dev server. Browser opens and navigates automatically to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Build ## Build
-11497
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "nls-guilloche-generator", "name": "nls-guilloche-generator",
"version": "1.0.0-rc.7", "version": "1.0.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/nextlevelshit/nls-guilloche-generator" "url": "https://github.com/nextlevelshit/nls-guilloche-generator"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "nls-guilloche", "name": "nls-guilloche",
"version": "1.0.0-rc.7", "version": "1.0.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/nextlevelshit/nls-guilloche-generator" "url": "https://github.com/nextlevelshit/nls-guilloche-generator"
@@ -15,7 +15,7 @@
*/ */
import { ViewChild, Component, Input, Output, SimpleChanges, OnChanges, EventEmitter, HostListener } from '@angular/core'; import { ViewChild, Component, Input, Output, SimpleChanges, OnChanges, EventEmitter, HostListener } from '@angular/core';
import { Observable, interval, Subscription } from 'rxjs'; import { Observable, interval } from 'rxjs';
import * as Selection from 'd3-selection'; import * as Selection from 'd3-selection';
import * as Shape from 'd3-shape'; import * as Shape from 'd3-shape';
import * as Random from 'd3-random'; import * as Random from 'd3-random';
@@ -109,23 +109,42 @@ export class NlsGraphsComponent implements OnChanges {
const genShiftStart = this.shiftPoint(this.matrix.start, this.config.vectors.start); const genShiftStart = this.shiftPoint(this.matrix.start, this.config.vectors.start);
const genShiftEnd = this.shiftPoint(this.matrix.end, this.config.vectors.end, false); const genShiftEnd = this.shiftPoint(this.matrix.end, this.config.vectors.end, false);
console.log(this.matrix);
const curveList = [ const curveList = [
{ {
color: this.config.colors.primary, color: this.config.colors.primary,
start: genShiftStart.next().value, start: genShiftStart.next().value,
end: genShiftEnd.next().value end: genShiftEnd.next().value
// start: {
// point: this.matrix.start,
// vector: this.config.vectors.start
// },
// end: {
// point: this.matrix.end,
// vector: this.config.vectors.end
// }
}, },
{ {
color: this.config.colors.secondary, color: this.config.colors.secondary,
start: genShiftEnd.next().value, start: genShiftEnd.next().value,
end: genShiftStart.next().value end: genShiftStart.next().value
// end: {
// point: this.matrix.start,
// vector: this.config.vectors.start
// },
// start: {
// point: this.matrix.end,
// vector: this.config.vectors.end
// }
} }
]; ];
this.graphs = curveList.map(curve => { this.graphs = curveList.map(curve => {
return { return {
...this.adjustGraph(curve), ...this.adjustGraph(curve),
spread: this.config.spread spread: this.config.spread,
interval: this.config.interval
}; };
}); });
this.hash = this.historyService.hash(this.graphs); this.hash = this.historyService.hash(this.graphs);
@@ -172,46 +191,20 @@ export class NlsGraphsComponent implements OnChanges {
const canvasHeight = this.canvas.getBoundingClientRect().height; const canvasHeight = this.canvas.getBoundingClientRect().height;
const totalArea = Math.abs(canvasWidth * canvasHeight); const totalArea = Math.abs(canvasWidth * canvasHeight);
const totalCenter = this.math.centerOfArea(canvasWidth, canvasHeight); const totalCenter = this.math.centerOfArea(canvasWidth, canvasHeight);
const baseArea = Math.abs(this.config.width * this.config.height);
const baseScale = Math.pow(totalArea / baseArea * this.config.scale, 0.5);
const baseWidthScaled = baseScale * this.config.width;
const baseHeightScaled = baseScale * this.config.height;
const baseCenter = this.math.centerOfArea(
baseWidthScaled,
baseHeightScaled
);
if (this.config.autoHeight) {
// Snap bottom and top to window limits
return { return {
start: { start: {
x: totalCenter.x - baseCenter.x, x: 0,
y: canvasHeight y: canvasHeight - this.config.vectors.spacing - this.config.margin.y
}, },
end: { end: {
x: totalCenter.x + baseCenter.x, x: canvasWidth - this.config.vectors.spacing - this.config.margin.x,
y: 0 y: 0
}, },
width: canvasWidth, width: canvasWidth,
height: canvasHeight, height: canvasHeight,
center: totalCenter center: totalCenter
}; };
} else {
// Adjust matrix relatively to window size
return {
start: {
x: totalCenter.x - baseCenter.x,
y: totalCenter.y + baseCenter.y
},
end: {
x: totalCenter.x + baseCenter.x,
y: totalCenter.y - baseCenter.y
},
width: baseWidthScaled,
height: baseHeightScaled,
center: totalCenter
};
}
} }
private genVectorPoint(point: Point, vector: number) { private genVectorPoint(point: Point, vector: number) {
@@ -28,8 +28,6 @@ import { NlsCanvasService } from './../services/canvas.service';
import { NlsMathService } from './../services/math.service'; import { NlsMathService } from './../services/math.service';
import { NlsGraphService } from '../services/graph.service'; import { NlsGraphService } from '../services/graph.service';
const ANIMATION_INTERVAL = 30;
@Directive({ @Directive({
selector: '[nlsGuilloche]' selector: '[nlsGuilloche]'
}) })
@@ -91,14 +89,12 @@ export class NlsGuillocheDirective implements OnChanges, OnDestroy {
}); });
let i = 0; let i = 0;
this.animationInterval = setInterval(() => { this.animationInterval = setInterval(() => {
// this.animateGraph();
this.animateGraph(i++ % 1000 / 10000); this.animateGraph(i++ % 1000 / 10000);
}, ANIMATION_INTERVAL); }, this.graph.interval);
} else { } else {
if (this.animationInterval) { if (this.animationInterval) {
this.bounce = null; this.bounce = null;
clearInterval(this.animationInterval); clearInterval(this.animationInterval);
// return;
} }
} }
@@ -15,8 +15,10 @@
*/ */
export interface Config { export interface Config {
width: number; margin: {
height: number; x: number;
y: number;
};
start: { start: {
x: number; x: number;
y: number; y: number;
@@ -43,6 +45,6 @@ export interface Config {
stroke: any; stroke: any;
overlap: any; overlap: any;
scale: any; scale: any;
interval: number;
date?: Date; date?: Date;
autoHeight?: boolean;
} }
@@ -1,3 +1,4 @@
import { interval } from 'rxjs';
/** /**
* Copyright (C) 2018 Michael Czechowski <mail@dailysh.it> * Copyright (C) 2018 Michael Czechowski <mail@dailysh.it>
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -34,6 +35,7 @@ export interface Graph {
amount: number; amount: number;
spacing: number spacing: number
}; };
interval: number;
stroke: number; // stroke width stroke: number; // stroke width
nodes?: Point[]; // orientation points nodes?: Point[]; // orientation points
} }
@@ -0,0 +1,26 @@
/**
* Copyright (C) 2018 Michael Czechowski <mail@dailysh.it>
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { Point } from './point.model';
export interface Matrix {
start: Point;
end: Point;
center: Point;
width: number;
height: number;
unit?: number;
}
+25
View File
@@ -0,0 +1,25 @@
{ pkgs ? import <nixpkgs> {} }:
let
lib = import <nixpkgs/lib>;
buildNodeJs = pkgs.callPackage "${<nixpkgs>}/pkgs/development/web/nodejs/nodejs.nix" {
python = pkgs.python3;
};
nodejsVersion = lib.fileContents ./.nvmrc;
nodejs = buildNodeJs {
enableNpm = true;
version = nodejsVersion;
sha256 = "032801kg24j04xmf09m0vxzlcz86sv21s24lv9l4cfv08k1c4byp";
};
# Overlay to use custom nodejs for nodePackages
customPkgs = pkgs // { inherit nodejs; };
in customPkgs.mkShell {
buildInputs = with customPkgs; [
nodejs
nodePackages."@angular/cli"
];
}
+16 -6
View File
@@ -6,18 +6,20 @@
<div class="pb-5"> <div class="pb-5">
<h5>Grundfläche</h5> <h5>Grundfläche</h5>
<hr> <hr>
<div class="form-group"> <ng-container formGroupName="margin">
<div class="form-group mb-4">
<label class="form-control-label"> <label class="form-control-label">
Breite X-Achse
</label> </label>
<input type="number" class="form-control" formControlName="width"> <input type="number" class="form-control" min="0" formControlName="x">
</div> </div>
<div class="form-group"> <div class="form-group mb-4">
<label class="form-control-label"> <label class="form-control-label">
Höhe Y-Achse
</label> </label>
<input type="number" class="form-control" formControlName="height"> <input type="number" class="form-control" formControlName="y">
</div> </div>
</ng-container>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Skalierung Skalierung
@@ -106,6 +108,14 @@
<input type="number" class="form-control" formControlName="spacing"> <input type="number" class="form-control" formControlName="spacing">
</div> </div>
</ng-container> </ng-container>
<div class="form-group">
<label class="form-control-label">
Animationsinterval
</label>
<input type="number" class="form-control" formControlName="interval" min="0" max="1000" step="1">
</div>
<div class="form-group d-flex flex-colmn justify-content-between align-items-center mb-4"> <div class="form-group d-flex flex-colmn justify-content-between align-items-center mb-4">
<label class="form-control-label"> <label class="form-control-label">
Animation Animation
+10 -4
View File
@@ -19,8 +19,10 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
const fb = new FormBuilder(); const fb = new FormBuilder();
export let ConfigForm: FormGroup = fb.group({ export let ConfigForm: FormGroup = fb.group({
width: fb.control('', Validators.required), margin: fb.group({
height: fb.control('', Validators.required), x: fb.control('', Validators.min(0)),
y: fb.control('', Validators.min(0))
}),
vectors: fb.group({ vectors: fb.group({
start: fb.control('', Validators.compose([ start: fb.control('', Validators.compose([
Validators.min(0), Validators.min(0),
@@ -45,7 +47,7 @@ export let ConfigForm: FormGroup = fb.group({
])), ])),
scale: fb.control('', Validators.compose([ scale: fb.control('', Validators.compose([
Validators.min(0), Validators.min(0),
Validators.max(1) Validators.max(10)
])), ])),
stroke: fb.control('', Validators.compose([ stroke: fb.control('', Validators.compose([
Validators.min(0.1), Validators.min(0.1),
@@ -58,5 +60,9 @@ export let ConfigForm: FormGroup = fb.group({
Validators.min(0), Validators.min(0),
Validators.max(50) Validators.max(50)
])), ])),
}) }),
interval: fb.control('', Validators.compose([
Validators.min(0),
Validators.max(1000)
])),
}); });
+23
View File
@@ -0,0 +1,23 @@
/**
* Copyright (C) 2018 Michael Czechowski <mail@dailysh.it>
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
const fb = new FormBuilder();
export let PresetForm: FormGroup = fb.group({
canvas: fb.control('')
});
+15
View File
@@ -0,0 +1,15 @@
export const CanvasPresets = [
{
title: 'Visitenkarte (hochkant)',
defaults: {
canvas: {
width: 284,
height: 482
},
margin: {
x: 28,
y: 272
}
}
}
];
+6 -1
View File
@@ -26,6 +26,10 @@ export const environment = {
autoHeight: false autoHeight: false
}, },
formDefaults: { formDefaults: {
margin: {
x: 0,
y: 0
},
width: 10, width: 10,
height: 16, height: 16,
scale: 0.4, scale: 0.4,
@@ -41,6 +45,7 @@ export const environment = {
spread: { spread: {
amount: 28, amount: 28,
spacing: 16 spacing: 16
} },
interval: 30
} }
}; };
+13 -10
View File
@@ -18,29 +18,32 @@ export const environment = {
production: false, production: false,
debug: false, debug: false,
animation: false, animation: false,
animationInterval: 30,
config: { config: {
colors: { colors: {
primary: '#129490', primary: '#129490',
secondary: '#CE1483' secondary: '#CE1483'
}, }
autoHeight: true
}, },
formDefaults: { formDefaults: {
width: 1e-10, margin: {
height: 1, x: 0,
y: 0
},
scale: 0.4, scale: 0.4,
overlap: 0.3, overlap: 0.5,
vectors: { vectors: {
start: 1, start: 0.5,
end: 0, end: 0,
range: 0.6, range: 0.2,
spacing: 7 spacing: 7
}, },
nodes: 3, nodes: 4,
stroke: 0.7, stroke: 0.7,
spread: { spread: {
amount: 30, amount: 60,
spacing: 20 spacing: 20
} },
interval: 30
} }
}; };
File diff suppressed because it is too large. Load diff