package iace import ( "archive/zip" "bytes" "encoding/xml" "fmt" ) // buildAssessmentMap builds a map from hazardID string to the latest RiskAssessment. func buildAssessmentMap(assessments []RiskAssessment) map[string]*RiskAssessment { m := make(map[string]*RiskAssessment) for i := range assessments { a := &assessments[i] key := a.HazardID.String() if existing, ok := m[key]; !ok || a.Version > existing.Version { m[key] = a } } return m } // riskLevelColor returns RGB values for PDF fill color based on risk level. func riskLevelColor(level RiskLevel) (r, g, b int) { switch level { case RiskLevelNotAcceptable: return 180, 0, 0 case RiskLevelVeryHigh: return 220, 40, 40 case RiskLevelCritical: return 255, 80, 80 case RiskLevelHigh: return 255, 165, 80 case RiskLevelMedium: return 255, 230, 100 case RiskLevelLow: return 180, 230, 140 case RiskLevelNegligible: return 140, 210, 140 default: return 240, 240, 240 } } // riskLevelLabel returns a German display label for a risk level. func riskLevelLabel(level RiskLevel) string { switch level { case RiskLevelNotAcceptable: return "Nicht akzeptabel" case RiskLevelVeryHigh: return "Sehr hoch" case RiskLevelCritical: return "Kritisch" case RiskLevelHigh: return "Hoch" case RiskLevelMedium: return "Mittel" case RiskLevelLow: return "Niedrig" case RiskLevelNegligible: return "Vernachlaessigbar" default: return string(level) } } // reductionTypeLabel returns a German label for a reduction type. func reductionTypeLabel(rt ReductionType) string { switch rt { case ReductionTypeDesign: return "Konstruktiv" case ReductionTypeProtective: return "Schutzmassnahme" case ReductionTypeInformation: return "Information" default: return string(rt) } } // mitigationStatusLabel returns a German label for a mitigation status. func mitigationStatusLabel(status MitigationStatus) string { switch status { case MitigationStatusPlanned: return "Geplant" case MitigationStatusImplemented: return "Umgesetzt" case MitigationStatusVerified: return "Verifiziert" case MitigationStatusRejected: return "Abgelehnt" default: return string(status) } } // regulationLabel returns a German label for a regulation type. func regulationLabel(reg RegulationType) string { switch reg { case RegulationNIS2: return "NIS-2 Richtlinie" case RegulationAIAct: return "EU AI Act" case RegulationCRA: return "Cyber Resilience Act" case RegulationMachineryRegulation: return "EU Maschinenverordnung 2023/1230" default: return string(reg) } } // escapeXML escapes special XML characters in text content. func escapeXML(s string) string { var buf bytes.Buffer if err := xml.EscapeText(&buf, []byte(s)); err != nil { return s } return buf.String() } // countByRiskLevel counts assessments per risk level. func countByRiskLevel(assessments []RiskAssessment) map[RiskLevel]int { counts := make(map[RiskLevel]int) for _, a := range assessments { counts[a.RiskLevel]++ } return counts } // pdfTruncate truncates a string for PDF cell display. func pdfTruncate(s string, maxLen int) string { runes := []rune(s) if len(runes) <= maxLen { return s } if maxLen <= 3 { return string(runes[:maxLen]) } return string(runes[:maxLen-3]) + "..." } // cellRef builds an Excel cell reference like "A1", "B12". func cellRef(col string, row int) string { return fmt.Sprintf("%s%d", col, row) } // rgbHex converts RGB values to a hex color string (without #). func rgbHex(r, g, b int) string { return fmt.Sprintf("%02X%02X%02X", r, g, b) } // addZipEntry writes a text file into a zip archive. func addZipEntry(zw *zip.Writer, name, content string) error { w, err := zw.Create(name) if err != nil { return err } _, err = w.Write([]byte(content)) return err } // docxHeading builds a DOCX paragraph with a heading style. func docxHeading(text string, level int) string { sizes := map[int]int{1: 64, 2: 52, 3: 44} sz, ok := sizes[level] if !ok { sz = 44 } escaped := escapeXML(text) return fmt.Sprintf(` %s `, level, sz, sz, escaped) } // docxParagraph builds a DOCX paragraph, optionally italic. func docxParagraph(text string, italic bool) string { escaped := escapeXML(text) rpr := "" if italic { rpr = "" } return fmt.Sprintf(` %s %s `, rpr, escaped) }