133 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Globalization;
 | 
						|
using System.Linq;
 | 
						|
using System.Text.Json.Nodes;
 | 
						|
 | 
						|
namespace Elwig.Helpers.Billing {
 | 
						|
    public class PaymentBillingData : BillingData {
 | 
						|
 | 
						|
        protected readonly Dictionary<int, Curve> Curves;
 | 
						|
        protected readonly Dictionary<string, Curve> PaymentData;
 | 
						|
        protected readonly Dictionary<string, Curve> QualityData;
 | 
						|
        protected readonly IEnumerable<string> AttributeVariants;
 | 
						|
 | 
						|
        public PaymentBillingData(JsonObject data, IEnumerable<string> attributeVariants) :
 | 
						|
            base(data) {
 | 
						|
            if (attributeVariants.Any(e => e.Any(c => c < 'A' || c > 'Z')))
 | 
						|
                throw new ArgumentException("Invalid attributeVariants");
 | 
						|
            AttributeVariants = attributeVariants;
 | 
						|
            Curves = GetCurves();
 | 
						|
            PaymentData = GetPaymentData();
 | 
						|
            QualityData = GetQualityData();
 | 
						|
        }
 | 
						|
 | 
						|
        public static PaymentBillingData FromJson(string json, IEnumerable<string> attributeVariants) {
 | 
						|
            return new(ParseJson(json), attributeVariants);
 | 
						|
        }
 | 
						|
 | 
						|
        private Dictionary<string, Curve> GetData(JsonObject data) {
 | 
						|
            Dictionary<string, Curve> dict;
 | 
						|
            if (data["default"] is JsonValue def) {
 | 
						|
                var c = LookupCurve(def);
 | 
						|
                dict = AttributeVariants.ToDictionary(e => e, _ => c);
 | 
						|
            } else {
 | 
						|
                dict = [];
 | 
						|
            }
 | 
						|
 | 
						|
            var variants = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length == 2);
 | 
						|
            var attributes = data.Where(p => p.Key.StartsWith('/'));
 | 
						|
            var others = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length > 2);
 | 
						|
            foreach (var (idx, v) in variants) {
 | 
						|
                var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
 | 
						|
                foreach (var i in AttributeVariants.Where(e => e.StartsWith(idx[..^1]))) {
 | 
						|
                    dict[i] = curve;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            foreach (var (idx, v) in attributes) {
 | 
						|
                var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
 | 
						|
                foreach (var i in AttributeVariants.Where(e => e[2..] == idx[1..])) {
 | 
						|
                    dict[i] = curve;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            foreach (var (idx, v) in others) {
 | 
						|
                var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
 | 
						|
                dict[idx.Replace("/", "")] = curve;
 | 
						|
            }
 | 
						|
 | 
						|
            return dict;
 | 
						|
        }
 | 
						|
 | 
						|
        protected Dictionary<string, Curve> GetPaymentData() {
 | 
						|
            var p = GetPaymentEntry();
 | 
						|
            if (p is JsonValue val) {
 | 
						|
                var c = LookupCurve(val);
 | 
						|
                return AttributeVariants.ToDictionary(e => e, _ => c);
 | 
						|
            }
 | 
						|
            return GetData(p?.AsObject() ?? throw new InvalidOperationException());
 | 
						|
        }
 | 
						|
 | 
						|
        protected Dictionary<string, Curve> GetQualityData() {
 | 
						|
            Dictionary<string, Curve> dict = [];
 | 
						|
            var q = GetQualityEntry();
 | 
						|
            if (q == null) return dict;
 | 
						|
 | 
						|
            foreach (var (qualid, data) in q) {
 | 
						|
                Dictionary<string, Curve> qualDict;
 | 
						|
                if (data is JsonValue val) {
 | 
						|
                    var c = LookupCurve(val);
 | 
						|
                    qualDict = AttributeVariants.ToDictionary(e => e, _ => c);
 | 
						|
                } else {
 | 
						|
                    qualDict = GetData(data?.AsObject() ?? throw new InvalidOperationException());
 | 
						|
                }
 | 
						|
                foreach (var (idx, d) in qualDict) {
 | 
						|
                    dict[$"{qualid}/{idx}"] = d;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return dict;
 | 
						|
        }
 | 
						|
 | 
						|
        public decimal CalculatePrice(string sortid, string? attrid, string qualid, bool gebunden, double oe, double kmw) {
 | 
						|
            var curve = GetQualityCurve(qualid, sortid, attrid) ?? GetCurve(sortid, attrid);
 | 
						|
            var d = (gebunden ? curve.Gebunden : null) ?? curve.Normal;
 | 
						|
            if (d.Count == 1) return d.First().Value;
 | 
						|
 | 
						|
            var r = curve.Mode == CurveMode.Oe ? oe : kmw;
 | 
						|
            var lt = d.Keys.Where(v => v <= r);
 | 
						|
            var gt = d.Keys.Where(v => v >= r);
 | 
						|
            if (!lt.Any()) {
 | 
						|
                return d[gt.Min()];
 | 
						|
            } else if (!gt.Any()) {
 | 
						|
                return d[lt.Max()];
 | 
						|
            }
 | 
						|
 | 
						|
            var max = lt.Max();
 | 
						|
            var min = gt.Min();
 | 
						|
            if (max == min) return d[r];
 | 
						|
 | 
						|
            var p1 = ((decimal)r - (decimal)min) / ((decimal)max - (decimal)min);
 | 
						|
            var p2 = 1 - p1;
 | 
						|
            return d[min] * p2 + d[max] * p1;
 | 
						|
        }
 | 
						|
 | 
						|
        private Curve LookupCurve(JsonValue val) {
 | 
						|
            if (val.TryGetValue(out string? curve)) {
 | 
						|
                var curveId = int.Parse(curve.Split(":")[1]);
 | 
						|
                return Curves[curveId];
 | 
						|
            } else if (val.TryGetValue(out decimal value)) {
 | 
						|
                return new(CurveMode.Oe, new() { { 73, value } }, null);
 | 
						|
            }
 | 
						|
            throw new InvalidOperationException();
 | 
						|
        }
 | 
						|
 | 
						|
        protected Curve GetCurve(string sortid, string? attrid) {
 | 
						|
            return PaymentData[$"{sortid}{attrid ?? ""}"];
 | 
						|
        }
 | 
						|
 | 
						|
        protected Curve? GetQualityCurve(string qualid, string sortid, string? attrid) {
 | 
						|
            return QualityData.TryGetValue($"{qualid}/{sortid}{attrid ?? ""}", out var curve) ? curve : null;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |