hash from ChatGpt

This commit is contained in:
Artur Kuś 2025-02-08 14:11:18 +01:00
parent c2d310ab62
commit 8569fc5310
2 changed files with 108 additions and 168 deletions

View File

@ -7,233 +7,172 @@ import { FormsModule } from '@angular/forms';
import { MatDatepicker, MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
import { MatInputModule } from '@angular/material/input';
import { format, parse, addMonths, isAfter } from 'date-fns';
import { format, parse } from 'date-fns';
import { createHash } from 'crypto';
interface FormValues {
initialValueAsset:number;
rate: number;
startDepreciation: Date;
typeDepreciation: TypeDepreciation;
factor: number;
}
class AssetLifeChangeWrapper{
class AssetLifeChangeWrapper {
when = signal<string>(YearMonth.todayTxt());
initial = signal<number>(0);
when = signal<string> ( YearMonth.todayTxt());
initial = signal<number>( 0 );
constructor( assetLifeChange : AssetLifeChange ){
constructor(assetLifeChange: AssetLifeChange) {
this.set(assetLifeChange);
}
}
get(): AssetLifeChange {
const ym = this.when();
const when = YearMonth.from( ym );
return new AssetLifeChange( when, this.initial() , 0, 0 );
return new AssetLifeChange(YearMonth.from(this.when()), this.initial(), 0, 0);
}
set(assetLifeChange: AssetLifeChange) {
this.when.set(YearMonth.toTxt(assetLifeChange.when));
this.initial.set(assetLifeChange.initial);
}
}
const NAME_IN_STORAGE = 'assetForCalculator';
const STORAGE_KEY = 'assetForCalculator';
const CACHE_KEY = 'cachedResults';
const HASH_KEY = 'assetHash';
@Component({
selector: 'app-asset-calculator',
standalone: true,
imports: [DecimalPipe, TranslateModule, FormsModule, MatDatepickerModule, MatNativeDateModule, MatInputModule],
providers: [
MatDatepickerModule,
MatNativeDateModule
],
providers: [MatDatepickerModule, MatNativeDateModule],
templateUrl: "asset-calculator.component.html",
styleUrls: ['asset-calculator.component.css']
})
export class AssetCalculatorComponent {
TypeDepreciation = TypeDepreciation;
// Signals for form state and amortizations
initialValueAsset = signal<number>(6000);
rate = signal<number>(20);
startDepreciation = signal<Date>(new Date());
typeDepreciation = signal<TypeDepreciation>(TypeDepreciation.linear);
factor = signal<number>(2);
lifeChangesSignal = signal<AssetLifeChangeWrapper[]>([]);
amortizationsSignal = signal<AssetPlanPosition[]>([]);
initialValueAsset = signal <number> ( 6000 );
rate = signal <number> ( 20 );
startDepreciation = signal <Date> ( new Date() );
typeDepreciation = signal <TypeDepreciation>( TypeDepreciation.linear );
factor = signal <number>( 2 );
constructor(private assetService: AssetService, private translate: TranslateService) {}
formValues = computed<FormValues>(() => {
return {
initialValueAsset: this.initialValueAsset(),
rate: this.rate(),
startDepreciation: this.startDepreciation(),
typeDepreciation: this.typeDepreciation(),
factor: this.factor(),
};
});
lifeChangesSignal = signal<AssetLifeChangeWrapper[]>([]); // Replaces `lifeFormArray`
amortizationsSignal =signal<AssetPlanPosition[]>([]);
constructor( private assetService: AssetService,
private translate : TranslateService ) {
// Effect to recalculate when form values change
effect( () => this.reCalculate( ) )
}
private storage = {
load: (key: string) => {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch {
console.error(`Failed to load ${key} from localStorage`);
return null;
}
},
save: (key: string, data: any) => {
try {
localStorage.setItem(key, JSON.stringify(data));
} catch {
console.error(`Failed to save ${key} to localStorage`);
}
}
};
ngOnInit(): void{
ngOnInit(): void {
this.restoreState();
}
ngOnDestroy(): void {
const asset = this.controlsToAsset( );
if( null != asset){
this.saveState( asset );
}
this.saveState(this.controlsToAsset());
}
private restoreState() {
const savedAsset = this.storage.load(NAME_IN_STORAGE);
if (savedAsset) this.assetToControls(savedAsset);
const savedAsset = localStorage.getItem(STORAGE_KEY);
const savedResults = localStorage.getItem(CACHE_KEY);
const savedHash = localStorage.getItem(HASH_KEY);
if (savedAsset) {
const asset: Asset = JSON.parse(savedAsset);
this.assetToControls(asset);
// Generujemy nowy hash
const newHash = this.generateHash(asset);
// Jeśli hash jest taki sam, ładujemy wyniki z cache
if (savedHash === newHash && savedResults) {
this.amortizationsSignal.set(JSON.parse(savedResults));
console.log("✅ Załadowano wyniki z cache brak przeliczeń.");
return;
}
console.log("🔄 Hash zmieniony wykonuję przeliczenie.");
this.reCalculate();
}
}
private saveState(asset: Asset) {
this.storage.save(NAME_IN_STORAGE, asset);
localStorage.setItem(STORAGE_KEY, JSON.stringify(asset));
localStorage.setItem(HASH_KEY, this.generateHash(asset)); // Zapisujemy nowy hash
}
private assetToControls( asset : Asset ) {
if( asset.life.length > 0 ){
this.updateBatch(asset);
}
}
private assetToControls(asset: Asset) {
if (!asset.life.length) return;
const [firstLife, ...restLives] = asset.life;
const method = asset.depreciationMethods[0];
private updateBatch(asset: Asset) {
const [firstLife, ...restLives] = asset.life;
const method0 = asset.depreciationMethods[0];
this.initialValueAsset.set(firstLife.initial);
this.startDepreciation.set(YearMonth.toDate(firstLife.when));
this.rate.set(method.rate);
this.typeDepreciation.set(method.type);
this.factor.set(method.factor);
this.lifeChangesSignal.set(restLives.map(life => new AssetLifeChangeWrapper(life)));
}
this.initialValueAsset.set(firstLife.initial);
this.startDepreciation.set(YearMonth.toDate(firstLife.when));
this.rate.set(method0.rate);
this.typeDepreciation.set(method0.type);
this.factor.set(method0.factor);
private controlsToAsset(): Asset {
const when = YearMonth.fromDate(this.startDepreciation());
const asset = new Asset(when);
const method = new AssetDepreciationMethod(when.year, this.rate(), this.typeDepreciation(), this.factor());
const lifeChanges = restLives.map((lifeChange) =>
new AssetLifeChangeWrapper(lifeChange)
);
this.lifeChangesSignal.set(lifeChanges);
}
asset.addMethod(method);
asset.addChange(new AssetLifeChange(when, this.initialValueAsset(), 0, 0));
this.lifeChangesSignal().forEach(lc => asset.addChange(lc.get()));
private controlsToAsset(): Asset {
return asset;
}
const formValues = this.formValues();
const lifeChanges = this.lifeChangesSignal();
private calculateToValues(positions: AssetPlanPosition[]) {
let sum = 0, sumThisYear = 0;
const when = YearMonth.fromDate( formValues.startDepreciation );
const asset = new Asset( when );
positions.forEach(pos => {
pos.calculatedDepreciation *= 0.01;
sum += pos.calculatedDepreciation;
pos.sum = sum;
sumThisYear = pos.when.month === 1 ? pos.calculatedDepreciation : sumThisYear + pos.calculatedDepreciation;
pos.sumThisYear = sumThisYear;
});
const method = new AssetDepreciationMethod( when.year, formValues.rate, formValues.typeDepreciation, formValues.factor );
asset.addMethod( method );
const creationLifeChange = new AssetLifeChange( when, formValues.initialValueAsset, 0, 0 );
asset.addChange( creationLifeChange );
lifeChanges.forEach((lifeChange) => {
asset.addChange( lifeChange.get() );
});
return asset;
}
private calculateToValues( positions:AssetPlanPosition[] ) {
let sum = 0;
let sumThisYear = 0;
positions.forEach( position => {
// From gr to zł or from cents to dollars it depends from currency
position.calculatedDepreciation *= 0.01;
sum += position.calculatedDepreciation;
position.sum = sum;
if( position.when.month === 1 ) {
sumThisYear = position.calculatedDepreciation;
} else {
sumThisYear += position.calculatedDepreciation;
}
position.sumThisYear = sumThisYear;
});
}
// Cache wyników
localStorage.setItem(CACHE_KEY, JSON.stringify(positions));
}
private reCalculate() {
const asset = this.controlsToAsset( );
this.calculateAmortizationsForAsset(asset);
this.saveState(asset);
this.calculateAmortizationsForAsset(this.controlsToAsset());
}
private calculateAmortizationsForAsset(asset: Asset) {
this.assetService.calculate(asset).subscribe((positions) => {
this.assetService.calculate(asset).subscribe(positions => {
this.calculateToValues(positions);
this.amortizationsSignal.set(positions);
});
}
clazz(pos : AssetPlanPosition ){
return pos.when.year % 2 === 0 ? "table-light" : "table-dark";
clazz(pos: AssetPlanPosition) {
return pos.when.year % 2 === 0 ? "table-light" : "table-dark";
}
// Method to add a life change
addLifeChange( ) {
const assetLifeChange2 : AssetLifeChange
= new AssetLifeChange( YearMonth.fromDate( this.formValues().startDepreciation ), 1000, 0, 0 );
return this.addLifeChange2( assetLifeChange2 );
addLifeChange(amount = 1000) {
const change = new AssetLifeChange(YearMonth.fromDate(this.startDepreciation()), amount, 0, 0);
this.lifeChangesSignal.update(changes => [...changes, new AssetLifeChangeWrapper(change)]);
}
addLifeChange2( assetLifeChange : AssetLifeChange ) {
const newChangeWrapper = new AssetLifeChangeWrapper( assetLifeChange );
this.lifeChangesSignal.update((changes) => [...changes, newChangeWrapper]);
return newChangeWrapper;
}
// Method to remove a life change
removeLifeChange(index: number) {
this.lifeChangesSignal.update((changes) =>
changes.filter((_, i) => i !== index)
);
this.lifeChangesSignal.update(changes => changes.filter((_, i) => i !== index));
}
updateDateFromInput(inputValue: string) {
// Konwersja stringa 'YYYY-MM' na Date
const parsedDate = parse(inputValue, 'yyyy-MM', new Date());
this.startDepreciation.set(parsedDate);
this.startDepreciation.set(parse(inputValue, 'yyyy-MM', new Date()));
}
onMonthSelected(event: Date, datepicker: MatDatepicker<Date>) {
this.startDepreciation.set(event); // Aktualizacja pola w formularzu
onMonthSelected(event: Date, datepicker: any) {
this.startDepreciation.set(event);
datepicker.close();
}
private generateHash(asset: Asset): string {
const data = JSON.stringify({
initialValue: asset.life[0]?.initial,
rate: asset.depreciationMethods[0]?.rate,
type: asset.depreciationMethods[0]?.type,
factor: asset.depreciationMethods[0]?.factor,
lifeChanges: asset.life.map(lc => ({ when: lc.when, initial: lc.initial }))
});
return createHash('sha256').update(data).digest('hex');
}
}

View File

@ -93,11 +93,12 @@ export class FixedAssetComponent {
private controlsToAssets(): [string, Asset][] {
const assets = new Map<string, Asset>();
const today = YearMonth.today();
this.assetFormArray.controls.forEach( control => {
const nrInv = control.get('nrInv')?.value;
const initialValue = control.get('initialValue')?.value;
const yearMonth = YearMonth.today();
const yearMonth = today;
const asset = new Asset( yearMonth );
const assetLifeChange = new AssetLifeChange( yearMonth, initialValue, 0, 0 );
asset.addChange( assetLifeChange );
@ -117,11 +118,11 @@ export class FixedAssetComponent {
this.addRow( "NrInv" + FixedAssetComponent.indexNr++, 1000 );
}
addRow( nrInv_:string, initial_: number ):void{
addRow( nrInv:string, initial: number ):void{
const newRow = this.fb.group({
nrInv : [ nrInv_ ],
initialValue : [ initial_ ],
nrInv : [ nrInv ],
initialValue : [ initial ],
});
// typeDepreciation : [ TypeDepreciation.linear ],