;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Project: AI and Lisp ;; Description: Common LISP und Code Generation with AI ;; ;; Customer : der_Wolfgang@forum@cad.de ;; Reference : https://ww3.cad.de/foren/ubb/Forum29/HTML/005012.shtml ;; Docu : C:\work\osd\....\common_lisp_with_AI.adoc ; ;; Author: der_Wolfgang@forum@cad.de ;; Created: Fri Aug 21 09:38:34 CEST 2026 ;; Modified: Sat Aug 22 13:42:38 CEST 2026 der_Wolfgang@forum@cad.de ;; SD-Version: developed with PE90 / cedm20.7, ;; should work in older versions as well as in big Modeling ;; Language: Lisp ;; Package: :cadde-wt ;; ;; (C) Copyright 2026 der_Wolfgang@forum@cad.de, all rights reserved. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; FILE SHOULD NOT BE LOADED in Modeling - because of example calls included ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (in-package :cadde-wt) (use-package :oli) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Ascii File Reader ;; PROMPT#1: "common lisp write a LISP ascii file reader" ;; Pure Common Lisp ASCII File Reader ;; Reads an ASCII text file and returns its contents as a list of strings. ;; Optionally prints each line to the console. (defun read-ascii-file (file-path &key (print-lines t)) "Read an ASCII text file from FILE-PATH and return a list of lines. If PRINT-LINES is true (default), also print each line to the console." (check-type file-path string) ;; Ensure FILE-PATH is a string ;; Check if file exists using built-in PROBE-FILE (unless (probe-file file-path) (format t "Error: File '~A' does not exist.~%" file-path) (return-from read-ascii-file nil)) (handler-case (with-open-file (stream file-path :direction :input :external-format :ascii) (loop for line = (read-line stream nil nil) while line collect (progn (when print-lines (format t "~A~%" line)) line))) (error (e) (format t "An error occurred while reading '~A': ~A~%" file-path e) nil))) ;; Example usage: ;; (read-ascii-file "example.txt") ;; Prints and returns list ;; (read-ascii-file "example.txt" :print-lines nil) ;; Returns list only ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun read-ascii-file-lines (filepath &key (trim-whitespace nil)) "Reads an ASCII text file and returns a list of strings, one per line. FILEPATH must be a string representing a valid file path. If TRIM-WHITESPACE is non-nil, leading/trailing spaces are removed." (check-type filepath string) ;; Ensure the argument is a string (let ((lines '())) (handler-case (with-open-file (stream filepath :direction :input :element-type 'character :if-does-not-exist nil) (if (null stream) (error "File not found: ~A" filepath) ;; Read each line until EOF (loop for raw-line = (read-line stream nil nil) while raw-line ;; Remove trailing carriage return for Windows CRLF for clean-line = (string-right-trim '(#\Return) raw-line) ;; Optionally trim whitespace for final-line = (if trim-whitespace (string-trim '(#\Space #\Tab) clean-line) clean-line) do (push final-line lines)))) (error (e) ;; Handle any I/O or type errors (format *error-output* "Error reading file '~A': ~A~%" filepath e) (return-from read-ascii-file-lines nil))) ;; Reverse to preserve original order (nreverse lines))) (when (probe-file "example.txt") ;; Example usage: (let ((file-lines (read-ascii-file-lines "example.txt" :trim-whitespace t))) (when file-lines (format t "Read ~D lines from file.~%" (length file-lines)) (dolist (line file-lines) (format t "~A~%" line)))) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Ascii File Reader - New AI Chat ;; PROMPT#1: "common lisp write a LISP ascii file reader" ;; Language: Common Lisp ;; This program reads an ASCII file and returns its content line by line. (defun read-ascii-file (filename) "Reads an ASCII text file and returns a list of its lines." (with-open-file (stream filename :direction :input :if-does-not-exist (error "File ~A does not exist." filename)) (let ((lines '())) ;; Loop through the file until end-of-file (loop for line = (read-line stream nil nil) while line do (push line lines)) ;; Reverse to maintain original order (nreverse lines)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Rolling LOG Files ;; PROMPT#1: Common Lisp: eine Schleife die von x auf 01 runterzählt und Dateien mit der Nummer umbennenet. (setq filebasename "c:/temp/cedm_startup_") (loop for i from (- 20 1) downto 0 for old = (format nil "~A~2,'0d.log" filebasename i) for new = (format nil "~A~2,'0d.log" filebasename (+ i 1)) when (probe-file old) do (rename-file old new)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; nun der erste Versuch mit untrainiertem Microsoft Copilot ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Modeling Dialog - Teile Flächen ;; PROMPT#1: Schreibe in Common LISP einen sd-defdialog für "Creo Elements/Direct Modeling" , ;; der ein Part auswählt und von diesem alle runden Flächen mit Ihren Eigenschaften ;; in der console auflistet. Zu den Eigenschaften zählen Radius, Achse, Achsrichtung, ;; Achspunkt, die Farbe und die 3D Box um die Fläche selbst. #| ######################## BAD CODE begins ################################# |# (when nil ;;; Sprache: Common LISP ;;; Beispiel: Einfacher SD-Dialog für Creo Elements/Direct Modeling ;;; Ziel: Part auswählen und im Dialog weiterverarbeiten ;#| ;;; Importiere nötige Module / Packages (require 'pdm) ; Pseudopaket für Creo Elements/Direct API (require 'sd) ; Pseudopaket für SD Dialoge ;;; Dialog definieren (sd-defdialog select-part-dialog "Part Selector" ;; Dialogfelder definieren (sd-dialog-entry "part-name" "Part Name" "") ; Textfeld für Partname (sd-dialog-button "select-part" "Select Part" ;; Funktions-Bindung beim Button-Click (lambda () ;; Part auswählen über Creo API (let ((selected-part (pdm:select-part))) ; Ruft Creo Auswahldialog auf (if selected-part (progn ;; Partname im Dialogfeld anzeigen (sd-dialog-set "part-name" (pdm:part-name selected-part)) ;; Hier kann zusätzliche Logik erfolgen, z.B. Part öffnen (pdm:open-part selected-part)) ;; Abbrechen / keine Auswahl getroffen (sd-dialog-message "No part selected!")))))) ;;; Dialog starten (sd-dialog-run select-part-dialog) ;|# ;;; Nutzung / Testfall ;; Wenn man die Funktion startet, öffnet sich der Dialog ;; und ermöglicht die Auswahl eines Parts im aktuellen Creo-Projekt ; Common LISP Code für Creo Elements/Direct Modeling ; Dieser Dialog erlaubt die Auswahl eines Parts (in-package :modeler) ; Sicherstellen, dass wir im Creo/Direct Paket arbeiten ; Dialog Definition (sd-defdialog select-part-dialog () "Dialog zur Part Auswahl" ;; Definition des Dialog-Layouts (sd-panel "Part Auswahl Panel" (sd-column-layout) ;; Part Auswahl Feld (sd-row (sd-label "Wähle ein Part:") (sd-object-select 'selected-part nil '(:type :part)) ) ;; Buttons (sd-row (sd-button "OK" :action (lambda () (if selected-part (progn (format t "Ausgewähltes Part: ~A~%" selected-part) (sd-close-dialog)) ; Schließt den Dialog (format t "Kein Part ausgewählt.~%")))) (sd-button "Abbrechen" :action (lambda () (format t "Dialog abgebrochen.~%") (sd-close-dialog)))) ) ) ; Beispiel zum Öffnen des Dialogs (defun open-part-dialog () (sd-run-dialog 'select-part-dialog)) ; Aufruf: (open-part-dialog) #| ######################## BAD CODE ends ################################### |# ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Dialog mit Baugruppen und Teilen ;; PROMPT#1: schreibe einen dialog mit kombinierten Auswahl von teilen / Baugruppen. Der button title ;; sollte sich nach einzel auswahl auf “teil” bzw “Baugruppe” ändern, sonst die anzahl der ;; selektieren elemten nennen . Alle Ttiel und Prompts 2 sprachig in deutsch und english (sd-defdialog 'select_parts_and_assemblies :dialog-title '(sd-multi-lang-string "Select Parts or Assemblies" :german "Teile oder Baugruppen auswählen") :variables '( (SELECTION :title (sd-multi-lang-string "Selection" :german "Auswahl") :value-type :part-assembly :multiple-items t :prompt-text (sd-multi-lang-string "Select parts or assemblies" :german "Teile oder Baugruppen auswählen") :initial-value nil :after-input #'(lambda (objs) (let* ((count (length objs))) (cond ((= count 1) (let ((obj (first objs))) (if (sd-inq-part-p obj) (progn (sd-set-variable-ui-properties 'selection :gui-value (sd-inq-obj-pathname obj) :title (sd-multi-lang-string "Part" :german "Teil"))) (if (sd-inq-assembly-p obj) (sd-set-variable-ui-properties 'selection :gui-value (sd-inq-obj-pathname obj) :title (sd-multi-lang-string "Assembly" :german "Baugruppe")) (sd-set-variable-ui-properties 'selection :gui-value (sd-inq-obj-pathname obj) :title (sd-multi-lang-string "Object" :german "Objekt")))))) ((> count 1) (sd-set-variable-ui-properties 'selection :gui-value (sd-multi-lang-string (format nil "~A objects selected" count) :german (format nil "~A Objekte ausgewählt" count)) :title (sd-multi-lang-string "Selection" :german "Auswahl"))) (t (sd-set-variable-ui-properties 'selection :gui-value "" :title (sd-multi-lang-string "Selection" :german "Auswahl")))))) ) ) :ok-action '(display (format nil (sd-multi-lang-string "You selected ~A object(s)." :german "Sie haben ~A Objekt(e) ausgewählt.") (length selection))) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - 2D Box um Workplane Geometrie ;; PROMPT#1: schreibe eine funktion sd-inq-wp-geo-bounding-box ..... (defun sd-inq-wp-geo-bounding-box (wp) ;; Hole alle Edges auf der Workplane (let* ((edges (sd-call-cmds (get_selection :select :edge :from_wp wp))) (x-list nil) (y-list nil)) ;; Loop über alle Edges (dolist (edge edges) ;; Hole die Eckpunkte (ll-pnt und ur-pnt) (let* ((edge-struct (sd-inq-edge-geo edge :dest-space :local)) (ll-pnt (sd-edge-ll-pnt edge-struct)) (ur-pnt (sd-edge-ur-pnt edge-struct))) ;; Sammle X- und Y-Koordinaten (when ll-pnt (push (gpnt3d_x ll-pnt) x-list) (push (gpnt3d_y ll-pnt) y-list)) (when ur-pnt (push (gpnt3d_x ur-pnt) x-list) (push (gpnt3d_y ur-pnt) y-list)))) ;; Sortiere die Listen (setq x-list (sort x-list #'<)) (setq y-list (sort y-list #'<)) ;; Gib kleinste und größte Werte aus (list (first x-list) (last x-list) (first y-list) (last y-list))) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - API: uwgm attribute handling ;; PROMPT#1: Schreibe eine LISP funktion (defun sd-uwgm-set-attributes (obj prop-list) ;; Prop list ist eine KEY-VALUE list, mit key==:keyword und value==strings. ;; für jede propertiey rufe die funktion (sd-uwgm-set-model-attribute obj attr-name attr-value). ;; mit attr.name== the key und attr-value == the value. ;; Schreibe nur attribute die ein String sind welcher nicht leer ist. (defun sd-uwgm-set-attributes (obj prop-list) (loop for (attr-name attr-value) on prop-list by #'cddr do (when (and (stringp attr-value) (> (length attr-value) 0)) (sd-uwgm-set-model-attribute obj (string-downcase (symbol-name attr-name)) attr-value))) ) ;; PROMPT#2: jetzt brauche ich das gegen part ;; (defun sd-uwgm-get-attributes (obj list-of-keys) ;; ... (sd-uwgm-get-model-attribute obj one-key) ;; ==> in eine propertliste wie oben (defun sd-uwgm-get-attributes (obj list-of-keys) (loop for attr-name in list-of-keys for attr-value = (sd-uwgm-get-model-attribute obj attr-name) when (and (stringp attr-value) (> (length attr-value) 0)) append (list attr-name attr-value)) ) ;; PROMPT#3: append is SEHR speicher intensive. Das geht doch besser ! (defun sd-uwgm-get-attributes (obj list-of-keys) (loop for attr-name in list-of-keys for attr-value = (sd-uwgm-get-model-attribute obj attr-name) when (and (stringp attr-value) (> (length attr-value) 0)) nconc (list attr-name attr-value)) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aufgabe: - Funktion für Zufalls ID ;; PROMPT#1: genriere eine common lisp funktion die einen Globally Unique Identifier als String zurückliefert (defun generate-random-uuid-string () "generates a random UUID version 4 as a string." (let ((bytes (loop repeat 16 collect (random 256)))) ;; Setze die UUID-Version (Byte 6, Bits 4..7 auf 4) (setf (nth 6 bytes) (logior (logand (nth 6 bytes) #b00001111) #b01000000)) ;; Setze das Variant-Feld (Byte 8, Bits 6..7 auf 10) (setf (nth 8 bytes) (logior (logand (nth 8 bytes) #b00111111) #b10000000)) (format nil "~2,'0X~2,'0X~2,'0X~2,'0X-~2,'0X~2,'0X-~2,'0X~2,'0X-~2,'0X~2,'0X-~2,'0X~2,'0X~2,'0X~2,'0X" (nth 0 bytes) (nth 1 bytes) (nth 2 bytes) (nth 3 bytes) (nth 4 bytes) (nth 5 bytes) (nth 6 bytes) (nth 7 bytes) (nth 8 bytes) (nth 9 bytes) (nth 10 bytes) (nth 11 bytes) (nth 12 bytes) (nth 13 bytes) (nth 14 bytes) (nth 15 bytes)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;