Поздравления с помощью AutoCAD
Автор: Кулик Алексей aka kpblc | Дата: 13 Февраль 2015 · 1 комментарий
Близятся первые праздники “общенационального” масштаба, хочется поздравить. Вопрос - как сделать так, чтобы сам ACAD поздравлял народ.
Сначала нарисуем простую функцию, вываливающую стандартное поздравление:
1 2 3 4 | (defun c:congr1 () (alert "Поздравляем с праздником!") (princ) ) ;_ end of defun |
Грустно, тупо и неинтересно. Намного любопытнее будет, если у нас в каком-то серверном каталоге лежит текстовый файлик примерно такого содержания:
1 | <Логин пользователя>;<Домен пользователя>;<Полные Фамилия, Имя, Отчество> |
Тогда обращение можно будет персонализировать:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | (defun c:conrg2 (/ _kpblc-conv-string-to-list handle file lst str user) (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (setq file "\\\\server\\библиотека\\test\\users.txt" ;; Путь к текстовому файлу handle (open file "r") ) ;_ end of setq (while (setq str (read-line handle)) (setq lst (cons (mapcar (function cons) '("user" "domain" "name") (_kpblc-conv-string-to-list str ";")) lst ) ;_ end of cons ) ;_ end of setq ) ;_ end of while (close handle) (if (setq user (car (vl-remove-if-not (function (lambda (x) (and (= (strcase (getenv "username")) (strcase (cdr (assoc "user" x)))) (= (strcase (getenv "userdomain")) (strcase (cdr (assoc "domain" x)))) ) ;_ end of and ) ;_ end of lambda ) ;_ end of function lst ) ;_ end of vl-remove-if-not ) ;_ end of car ) ;_ end of setq (alert (strcat "Уважаемый(ая) " (cdr (assoc "name" user)) "!" "\n\nПоздравляем с праздником!" ) ;_ end of strcat ) ;_ end of alert ) ;_ end of if (princ) ) ;_ end of defun |
Но это поздравление тоже не совсем "нормальное": что значит "Уважаемый(ая)"? Добавим пол: мужской-женский в файл:
1 | <Логин пользователя>;<Домен пользователя>;<Полные Фамилия, Имя, Отчество>;<Пол> |
и поменяем код (указываем пол “м” - мужской; “ж” - женский):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | (defun c:conrg3 (/ _kpblc-conv-string-to-list handle file lst str user) (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (setq file "\\\\server\\библиотека\\test\\users.txt" ;; Путь к текстовому файлу handle (open file "r") ) ;_ end of setq (while (setq str (read-line handle)) (setq lst (cons (mapcar (function cons) '("user" "domain" "name" "sex") (_kpblc-conv-string-to-list str ";")) lst ) ;_ end of cons ) ;_ end of setq ) ;_ end of while (close handle) (if (setq user (car (vl-remove-if-not (function (lambda (x) (and (= (strcase (getenv "username")) (strcase (cdr (assoc "user" x)))) (= (strcase (getenv "userdomain")) (strcase (cdr (assoc "domain" x)))) ) ;_ end of and ) ;_ end of lambda ) ;_ end of function lst ) ;_ end of vl-remove-if-not ) ;_ end of car ) ;_ end of setq (alert (strcat "Уважаем" (if (member (strcase (cdr (assoc "sex" user))) '("M" "М")) "ый" "ая" ) ;_ end of if " " (cdr (assoc "name" user)) "!" "\n\nПоздравляем с праздником!" ) ;_ end of strcat ) ;_ end of alert ) ;_ end of if (princ) ) ;_ end of defun |
Слегка пообщавшись с пользователями, решили добавить вариант “данных о пользователе нет”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | (defun c:conrg4 (/ _kpblc-conv-string-to-list handle file lst str user) (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (setq file "\\\\server\\библиотека\\test\\users.txt" ;; Путь к текстовому файлу handle (open file "r") ) ;_ end of setq (while (setq str (read-line handle)) (setq lst (cons (mapcar (function cons) '("user" "domain" "name" "sex") (_kpblc-conv-string-to-list str ";")) lst ) ;_ end of cons ) ;_ end of setq ) ;_ end of while (close handle) (if (setq user (car (vl-remove-if-not (function (lambda (x) (and (= (strcase (getenv "username")) (strcase (cdr (assoc "user" x)))) (= (strcase (getenv "userdomain")) (strcase (cdr (assoc "domain" x)))) ) ;_ end of and ) ;_ end of lambda ) ;_ end of function lst ) ;_ end of vl-remove-if-not ) ;_ end of car ) ;_ end of setq (alert (strcat "Уважаем" (if (member (strcase (cdr (assoc "sex" user))) '("M" "М")) "ый" "ая" ) ;_ end of if " " (cdr (assoc "name" user)) "!" "\n\nПоздравляем с праздником!" ) ;_ end of strcat ) ;_ end of alert (alert "Принимайте поздравления!") ) ;_ end of if (princ) ) ;_ end of defun |
Если файл конфигурировать лениво или долго, поступим так: прямо внутрь кода загоняем возможные тексты поздравлений и вызываем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | (defun c:conrg5 (/ lst _dwgru-random) (defun _dwgru-random (/ modulus multiplier increment) ;;; Генерирует случайное вещественное число в диапазоне от 0 до 1 ;;; Используется глобальная переменная *DWGRU_SEED* (if (not *dwgru_seed*) (setq *dwgru_seed* (getvar "DATE")) ) ;_ end of if (setq modulus 65536 multiplier 25173 increment 13849 *dwgru_seed* (rem (+ (* multiplier *dwgru_seed*) increment) modulus) ) ;_ end of setq (/ *dwgru_seed* modulus) ) ;_ end of defun (setq lst '("Поздравление 1" "Поздравление 2" "Поздравление 3" "Поздравление 4" ) ) ;_ end of setq (alert (nth (fix (* (length lst) (_dwgru-random))) lst)) (princ) ) ;_ end of defun |
Если нарисовать такую команду да еще на нее и кнопочку дать, пользователи могут запросто забыть про работу и начать играться. Поэтому сделаем по-другому: во-первых, введем контроль по датам - команда должна срабатывать в последний рабочий день перед праздником (праздниками): Новый Год, 23 февраля, 8 Марта… Сделаем так, чтобы код не давал запускаться в нерабочий день и если до праздника меньше 4 календарных дней. А заодно сделаем так, чтобы он запускался только раз в сутки
Внимание! Коды, которые будут показаны ниже, работают таким образом, что больше одного раза в сутки срабатывать не будут! Если это надо снять, то сообщи
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | (defun congr6 (/ curday date _kpblc-conv-string-to-list _kpblc-conv-date-to-day _dwgru-random reghive regkey) (setq reghive "HKEY_CURRENT_USER\\Software\\kpblc\\AutodeskCommunity" regkey "LastStart" lst '("Поздравление 1" "Поздравление 2" "Поздравление 3" "Поздравление 4" ) ) ;_ end of setq (defun _dwgru-random (/ modulus multiplier increment) ;;; Генерирует случайное вещественное число в диапазоне от 0 до 1 ;;; Используется глобальная переменная *DWGRU_SEED* (if (not *dwgru_seed*) (setq *dwgru_seed* (getvar "DATE")) ) ;_ end of if (setq modulus 65536 multiplier 25173 increment 13849 *dwgru_seed* (rem (+ (* multiplier *dwgru_seed*) increment) modulus) ) ;_ end of setq (/ *dwgru_seed* modulus) ) ;_ end of defun (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (defun _kpblc-conv-date-to-day (date / lst) ;| * Преобразование даты (в днях) в число от 01.01.1990 (пн) * Параметры вызова: date обрабатываемая дата Возможные значения: string ; Строка вида ГГГГММДД string ; Строка вида ГГГГ.ММ.ДД string ; Строка вида ГГММДД string ; Строка вида ГГ.ММ.ДД integer ; Число вида ГГГГММДД list ; Список. Варианты: '(year month day) '(("year" . <year>) ("month" . <month>) ("day" . <day>)) |; (cond ((= (type date) 'str) (if (= (length (setq lst (_kpblc-conv-string-to-list date "."))) 1) (cond ((= (strlen date) 6) (_kpblc-conv-date-to-day (list (cons "year" (+ (/ (- (fix (getvar "cdate")) (rem (fix (getvar "cdate")) 1e6)) 1e4) (atoi (substr date 1 2)) ) ;_ end of + ) ;_ end of cons (cons "month" (atoi (substr date 3 2))) (cons "day" (atoi (substr date 5 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ((= (strlen date) 8) (_kpblc-conv-date-to-day (list (cons "year" (atoi (substr date 1 4))) (cons "month" (atoi (substr date 5 2))) (cons "day" (atoi (substr date 7 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ) ;_ end of cond (_kpblc-conv-date-to-day (list (cons "year" (car lst)) (cons "month" (cond ((cadr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons (cons "day" (cond ((caddr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ;_ end of if ) ((= (type date) 'int) (_kpblc-conv-date-to-day (vl-princ-to-string date)) ) ((and (listp date) (not (listp (car date))) ) ;_ end of and (_kpblc-conv-date-to-day (list (cons "year" (car date)) (cons "month" (cadr date)) (cons "day" (caddr date))) ) ;_ end of _kpblc-conv-date-to-day ) ((and (listp date) (listp (car date)) ) ;_ end of and ((lambda (/ start_year fun_is-year-leap _d y) (defun fun_is-year-leap (yy / tt) (setq tt (/ yy 4.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 4, test for 100 year exception (setq tt (/ yy 100.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 100, test for 400 year double exception (setq tt (/ yy 400.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) t ;divisible by 400 is leap year nil ;divisible by 100 is not leap year ) ;_ end of if ) ;_ end of progn t ;divisible by 4 but not 100, is leap year ) ;_ end of if ) ;_ end of progn nil ) ;not divisible by 4, not a leap year ) ;_ end of defun (setq start_year 2012 _d (if (fun_is-year-leap (setq y (cond ((cdr (assoc "year" date))) (t start_year) ) ;_ end of cond ) ;_ end of setq ) ;_ end of fun_is-year-leap '(0 31 60 91 121 152 182 213 244 274 305 335) '(0 31 59 90 120 151 181 212 243 273 304 334) ) ;_ end of if ) ;_ end of setq (+ (* (- y start_year) 365) ;; (if (= 0 (rem (1- y) 4)) 1 0) (1+ (/ (- y start_year) 4)) ;; (/ (1- y) 4) ; 29 февраля всех весокосных лет кроме текущего (nth (1- (cond ((cdr (assoc "month" date))) (t 1) ) ;_ end of cond ) ;_ end of 1- _d ) ; дней с начала года до начала месяца (cond ((cdr (assoc "day" date))) (t 1) ) ; число ) ;_ end of + ) ;_ end of lambda ) ) ) ;_ end of cond ) ;_ end of defun (if (and (<= (setq curday (1- (rem (_kpblc-conv-date-to-day (itoa (setq date (fix (getvar "cdate"))))) 7))) 5 ) ;_ end of <= ;; День до пятницы включительно (apply (function or) (mapcar (function (lambda (x) ;; Разница между датой праздница и текущей меньше 4 дней. (< (- (atoi (strcat (itoa (fix (/ date 10000))) x)) date) 4) ) ;_ end of lambda ) ;_ end of function '("1231" "0223" "0308" ) ) ;_ end of mapcar ) ;_ end of apply (or (not (vl-registry-read reghive regkey)) (/= date (vl-registry-read reghive regkey)) ) ;_ end of or ) ;_ end of and (progn (vl-registry-write reghive regkey date) (alert (nth (fix (* (length lst) (_dwgru-random))) lst)) ) ;_ end of progn ) ;_ end of if (princ) ) ;_ end of defun |
Теперь будет достаточно добавить строку (conrg6) в любой автозагружаемый лисп - и viola, поздравления будут только раз в день, и случайным образом.
Попробуем теперь сделать так, чтобы ACAD вываливал html-страницу с поздравительной картинкой.
Сначала нарисуем код, который будет выводить картинку (jpg / png / gif), которая просто хранится на сервере в определенном каталоге (я для примера взял каталог c:\congrat):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | (defun congr7 (/ curday date _kpblc-conv-string-to-list _kpblc-conv-date-to-day _dwgru-random reghive regkey path) (setq reghive "HKEY_CURRENT_USER\\Software\\kpblc\\AutodeskCommunity" regkey "LastStart" lst '("Поздравление 1" "Поздравление 2" "Поздравление 3" "Поздравление 4" ) path "c:\\congrat" ) ;_ end of setq (defun _dwgru-random (/ modulus multiplier increment) ;;; Генерирует случайное вещественное число в диапазоне от 0 до 1 ;;; Используется глобальная переменная *DWGRU_SEED* (if (not *dwgru_seed*) (setq *dwgru_seed* (getvar "DATE")) ) ;_ end of if (setq modulus 65536 multiplier 25173 increment 13849 *dwgru_seed* (rem (+ (* multiplier *dwgru_seed*) increment) modulus) ) ;_ end of setq (/ *dwgru_seed* modulus) ) ;_ end of defun (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (defun _kpblc-conv-date-to-day (date / lst) ;| * Преобразование даты (в днях) в число от 01.01.1990 (пн) * Параметры вызова: date обрабатываемая дата Возможные значения: string ; Строка вида ГГГГММДД string ; Строка вида ГГГГ.ММ.ДД string ; Строка вида ГГММДД string ; Строка вида ГГ.ММ.ДД integer ; Число вида ГГГГММДД list ; Список. Варианты: '(year month day) '(("year" . <year>) ("month" . <month>) ("day" . <day>)) |; (cond ((= (type date) 'str) (if (= (length (setq lst (_kpblc-conv-string-to-list date "."))) 1) (cond ((= (strlen date) 6) (_kpblc-conv-date-to-day (list (cons "year" (+ (/ (- (fix (getvar "cdate")) (rem (fix (getvar "cdate")) 1e6)) 1e4) (atoi (substr date 1 2)) ) ;_ end of + ) ;_ end of cons (cons "month" (atoi (substr date 3 2))) (cons "day" (atoi (substr date 5 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ((= (strlen date) 8) (_kpblc-conv-date-to-day (list (cons "year" (atoi (substr date 1 4))) (cons "month" (atoi (substr date 5 2))) (cons "day" (atoi (substr date 7 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ) ;_ end of cond (_kpblc-conv-date-to-day (list (cons "year" (car lst)) (cons "month" (cond ((cadr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons (cons "day" (cond ((caddr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ;_ end of if ) ((= (type date) 'int) (_kpblc-conv-date-to-day (vl-princ-to-string date)) ) ((and (listp date) (not (listp (car date))) ) ;_ end of and (_kpblc-conv-date-to-day (list (cons "year" (car date)) (cons "month" (cadr date)) (cons "day" (caddr date))) ) ;_ end of _kpblc-conv-date-to-day ) ((and (listp date) (listp (car date)) ) ;_ end of and ((lambda (/ start_year fun_is-year-leap _d y) (defun fun_is-year-leap (yy / tt) (setq tt (/ yy 4.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 4, test for 100 year exception (setq tt (/ yy 100.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 100, test for 400 year double exception (setq tt (/ yy 400.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) t ;divisible by 400 is leap year nil ;divisible by 100 is not leap year ) ;_ end of if ) ;_ end of progn t ;divisible by 4 but not 100, is leap year ) ;_ end of if ) ;_ end of progn nil ) ;not divisible by 4, not a leap year ) ;_ end of defun (setq start_year 2012 _d (if (fun_is-year-leap (setq y (cond ((cdr (assoc "year" date))) (t start_year) ) ;_ end of cond ) ;_ end of setq ) ;_ end of fun_is-year-leap '(0 31 60 91 121 152 182 213 244 274 305 335) '(0 31 59 90 120 151 181 212 243 273 304 334) ) ;_ end of if ) ;_ end of setq (+ (* (- y start_year) 365) ;; (if (= 0 (rem (1- y) 4)) 1 0) (1+ (/ (- y start_year) 4)) ;; (/ (1- y) 4) ; 29 февраля всех весокосных лет кроме текущего (nth (1- (cond ((cdr (assoc "month" date))) (t 1) ) ;_ end of cond ) ;_ end of 1- _d ) ; дней с начала года до начала месяца (cond ((cdr (assoc "day" date))) (t 1) ) ; число ) ;_ end of + ) ;_ end of lambda ) ) ) ;_ end of cond ) ;_ end of defun (if (and (<= (setq curday (1- (rem (_kpblc-conv-date-to-day (itoa (setq date (fix (getvar "cdate"))))) 7))) 5 ) ;_ end of <= ;; День до пятницы включительно (apply (function or) (mapcar (function (lambda (x) ;; Разница между датой праздница и текущей меньше 4 дней. (< (- (atoi (strcat (itoa (fix (/ date 10000))) x)) date) 4) ) ;_ end of lambda ) ;_ end of function '("1231" "0223" "0308" ) ) ;_ end of mapcar ) ;_ end of apply (or (not (vl-registry-read reghive regkey)) (/= date (vl-registry-read reghive regkey)) ) ;_ end of or ) ;_ end of and (progn (vl-registry-write reghive regkey date) (alert (nth (fix (* (length lst) (_dwgru-random))) lst)) ;; Выводим окно (vl-catch-all-apply (function (lambda (/ files file objiea doc body) (if (setq files (vl-remove-if (function (lambda (x) (or (member x '("." "..")) (vl-file-directory-p x) (not (vl-filename-extension x)) (not (vl-filename-base x)) (not (wcmatch (strcase (vl-filename-extension x)) ".JPG,.PNG,.GIF")) ) ;_ end of or ) ;_ end of LAMBDA ) ;_ end of function (vl-directory-files path "*.*" 1) ) ;_ end of vl-remove-if ) ;_ end of setq (progn (setq file (nth (fix (* (length files) (_dwgru-random))) files) objiea (vlax-create-object "InternetExplorer.Application") ) ;_ end of setq (vlax-put-property objiea "Toolbar" 0) (vlax-put-property objiea "StatusBar" 0) (vlax-put-property objiea "Visible" :vlax-true) (vlax-invoke objiea "Navigate" (strcat (vl-string-right-trim "\" path) "\" file ) ;_ end of strcat ) ;_ end of vlax-invoke (while (/= 4 (vlax-get-property objiea "ReadyState")) (princ ".") ) ;_ end of while (setq doc (vlax-get-property objiea "Document") body (vlax-get-property doc "Body") ) ;_ end of setq ;; И записываем в реестр соответствующие данные ;; (vl-registry-write hive key (rtos date 2 4)) (command "_.delay" 10000) ) ;_ end of progn ) ;_ end of if ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of progn ) ;_ end of if (princ) ) ;_ end of defun |
Но возникает вопрос: а, может, стоит сделать так, чтобы создать подкаталоги, например, “0223” (февраль 23), “0308” (март 8) и тому подобное? И тогда уже делать подкаталоги картинок, чтобы на 23 народ получал танчики и девушек в форме, а на 8 марта - котят и цветы?
Давайте попробуем
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | (defun congr8 (/ curday date _kpblc-conv-string-to-list _kpblc-conv-date-to-day _dwgru-random reghive regkey path subpath) (setq reghive "HKEY_CURRENT_USER\\Software\\kpblc\\AutodeskCommunity" regkey "LastStart" lst '("Поздравление 1" "Поздравление 2" "Поздравление 3" "Поздравление 4" ) path "c:\\congrat" ) ;_ end of setq (defun _dwgru-random (/ modulus multiplier increment) ;;; Генерирует случайное вещественное число в диапазоне от 0 до 1 ;;; Используется глобальная переменная *DWGRU_SEED* (if (not *dwgru_seed*) (setq *dwgru_seed* (getvar "DATE")) ) ;_ end of if (setq modulus 65536 multiplier 25173 increment 13849 *dwgru_seed* (rem (+ (* multiplier *dwgru_seed*) increment) modulus) ) ;_ end of setq (/ *dwgru_seed* modulus) ) ;_ end of defun (defun _kpblc-conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (_kpblc-conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (_kpblc-conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) ((wcmatch (strcase string) (strcat "*" (strcase separator) "*")) ((lambda (/ pos res _str prev) (setq pos 1 prev 1 _str (substr string pos) ) ;_ end of setq (while (<= pos (1+ (- (strlen string) (strlen separator)))) (if ;; (wcmatch (strcase (substr string pos)) (strcase (strcat separator "*"))) (wcmatch (strcase (substr string pos (strlen separator))) (strcase separator)) (setq res (cons (substr string 1 (1- pos)) res) string (substr string (+ (strlen separator) pos)) pos 0 ) ;_ end of setq ) ;_ end of if (setq pos (1+ pos)) ) ;_ end of while (if (< (strlen string) (strlen separator)) (setq res (cons string res)) ) ;_ end of if (if (or (not res) (= _str string)) (setq res (list string)) (reverse res) ) ;_ end of if ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (defun _kpblc-conv-date-to-day (date / lst) ;| * Преобразование даты (в днях) в число от 01.01.1990 (пн) * Параметры вызова: date обрабатываемая дата Возможные значения: string ; Строка вида ГГГГММДД string ; Строка вида ГГГГ.ММ.ДД string ; Строка вида ГГММДД string ; Строка вида ГГ.ММ.ДД integer ; Число вида ГГГГММДД list ; Список. Варианты: '(year month day) '(("year" . <year>) ("month" . <month>) ("day" . <day>)) |; (cond ((= (type date) 'str) (if (= (length (setq lst (_kpblc-conv-string-to-list date "."))) 1) (cond ((= (strlen date) 6) (_kpblc-conv-date-to-day (list (cons "year" (+ (/ (- (fix (getvar "cdate")) (rem (fix (getvar "cdate")) 1e6)) 1e4) (atoi (substr date 1 2)) ) ;_ end of + ) ;_ end of cons (cons "month" (atoi (substr date 3 2))) (cons "day" (atoi (substr date 5 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ((= (strlen date) 8) (_kpblc-conv-date-to-day (list (cons "year" (atoi (substr date 1 4))) (cons "month" (atoi (substr date 5 2))) (cons "day" (atoi (substr date 7 2))) ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ) ;_ end of cond (_kpblc-conv-date-to-day (list (cons "year" (car lst)) (cons "month" (cond ((cadr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons (cons "day" (cond ((caddr lst)) (t 1) ) ;_ end of cond ) ;_ end of cons ) ;_ end of list ) ;_ end of _kpblc-conv-date-to-day ) ;_ end of if ) ((= (type date) 'int) (_kpblc-conv-date-to-day (vl-princ-to-string date)) ) ((and (listp date) (not (listp (car date))) ) ;_ end of and (_kpblc-conv-date-to-day (list (cons "year" (car date)) (cons "month" (cadr date)) (cons "day" (caddr date))) ) ;_ end of _kpblc-conv-date-to-day ) ((and (listp date) (listp (car date)) ) ;_ end of and ((lambda (/ start_year fun_is-year-leap _d y) (defun fun_is-year-leap (yy / tt) (setq tt (/ yy 4.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 4, test for 100 year exception (setq tt (/ yy 100.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) (progn ;; Divisible by 100, test for 400 year double exception (setq tt (/ yy 400.0)) (if (equal (- tt (fix tt)) 0.0 0.00001) t ;divisible by 400 is leap year nil ;divisible by 100 is not leap year ) ;_ end of if ) ;_ end of progn t ;divisible by 4 but not 100, is leap year ) ;_ end of if ) ;_ end of progn nil ) ;not divisible by 4, not a leap year ) ;_ end of defun (setq start_year 2012 _d (if (fun_is-year-leap (setq y (cond ((cdr (assoc "year" date))) (t start_year) ) ;_ end of cond ) ;_ end of setq ) ;_ end of fun_is-year-leap '(0 31 60 91 121 152 182 213 244 274 305 335) '(0 31 59 90 120 151 181 212 243 273 304 334) ) ;_ end of if ) ;_ end of setq (+ (* (- y start_year) 365) ;; (if (= 0 (rem (1- y) 4)) 1 0) (1+ (/ (- y start_year) 4)) ;; (/ (1- y) 4) ; 29 февраля всех весокосных лет кроме текущего (nth (1- (cond ((cdr (assoc "month" date))) (t 1) ) ;_ end of cond ) ;_ end of 1- _d ) ; дней с начала года до начала месяца (cond ((cdr (assoc "day" date))) (t 1) ) ; число ) ;_ end of + ) ;_ end of lambda ) ) ) ;_ end of cond ) ;_ end of defun (if (and (<= (setq curday (1- (rem (_kpblc-conv-date-to-day (itoa (setq date (fix (getvar "cdate"))))) 7))) 5 ) ;_ end of <= ;; День до пятницы включительно (apply (function or) (mapcar (function (lambda (x) ;; Разница между датой праздница и текущей меньше 4 дней. (< (- (atoi (strcat (itoa (fix (/ date 10000))) x)) date) 4) ) ;_ end of lambda ) ;_ end of function '("1231" "0223" "0308" ) ) ;_ end of mapcar ) ;_ end of apply (setq subpath (car (vl-sort (vl-remove-if-not (function (LAMBDA(x) (WCMATCH x "####"))) (VL-DIRECTORY-FILES path "*.*" -1)) (function (LAMBDA(a b) (< (atoi (strcat (itoa (fix (/ date 10000))) a))(atoi (strcat (itoa (fix (/ date 10000))) b)))))))) (or (not (vl-registry-read reghive regkey)) (/= date (vl-registry-read reghive regkey)) ) ;_ end of or ) ;_ end of and (progn (vl-registry-write reghive regkey date) (alert (nth (fix (* (length lst) (_dwgru-random))) lst)) ;; Выводим окно (vl-catch-all-apply (function (lambda (/ files file objiea doc body) (if (setq files (vl-remove-if (function (lambda (x) (or (member x '("." "..")) (vl-file-directory-p x) (not (vl-filename-extension x)) (not (vl-filename-base x)) (not (wcmatch (strcase (vl-filename-extension x)) ".JPG,.PNG,.GIF")) ) ;_ end of or ) ;_ end of LAMBDA ) ;_ end of function (vl-directory-files (strcat (VL-STRING-RIGHT-TRIM "\" path)"\" subpath) "*.*" 1) ) ;_ end of vl-remove-if ) ;_ end of setq (progn (setq file (nth (fix (* (length files) (_dwgru-random))) files) objiea (vlax-create-object "InternetExplorer.Application") ) ;_ end of setq (vlax-put-property objiea "Toolbar" 0) (vlax-put-property objiea "StatusBar" 0) (vlax-put-property objiea "Visible" :vlax-true) (vlax-invoke objiea "Navigate" (strcat (VL-STRING-RIGHT-TRIM "\" path)"\" subpath "\" file ) ;_ end of strcat ) ;_ end of vlax-invoke (while (/= 4 (vlax-get-property objiea "ReadyState")) (princ ".") ) ;_ end of while (setq doc (vlax-get-property objiea "Document") body (vlax-get-property doc "Body") ) ;_ end of setq ;; И записываем в реестр соответствующие данные ;; (vl-registry-write hive key (rtos date 2 4)) (command "_.delay" 10000) ) ;_ end of progn ) ;_ end of if ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of progn ) ;_ end of if (princ) ) ;_ end of defun |
Теперь, вместо (congr6) вбиваем (congr8) и наслаждаемся и текстовым поздравлением, и - отдельно - картинкой, показываемой в окне Internet Explorer’a.
P.S. Если надо сделать код, чтобы он срабатывал не "раз в сутки", а "при каждом новом запуске AutoCAD", сообщите - сделаем
Отлично, не вопрос. Правда, код, который здесь будет представлен, может использовать только уже оформленные html / htm – страницы. Если в наличии есть Help&Manual, то можно разработать справку и опубликовать ее в html-формате (я именно так и поступил). Теперь собственно код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | (defun tip-of-the-day (/ _dwgru-random vl-browsefiles-in-directory-nested path files file) ;; Путь к html-страницам с советами. Именно это надо менять в своих конкретных условиях: (setq path "\\\\server\\kulik\\HTML\") ;; Обратите внимание: слеши должны быть двойными! (defun _dwgru-random (/ modulus multiplier increment) ;;; Генерирует случайное вещественное число в диапазоне от 0 до 1 ;;; Используется глобальная переменная *DWGRU_SEED* (if (not *dwgru_seed*) (setq *dwgru_seed* (getvar "DATE")) ) ;_ end of if (setq modulus 65536 multiplier 25173 increment 13849 *dwgru_seed* (rem (+ (* multiplier *dwgru_seed*) increment) modulus) ) ;_ end of setq (/ *dwgru_seed* modulus) ) ;_ end of defun (defun vl-browsefiles-in-directory-nested (path mask) ;| * Функция возвращает список файлов указанной маски, находящихся в * заданном каталоге * Параметры вызова: path путь к корневому каталогу. nil недопустим mask маска имени файла. nil или список недопустим * Примеры вызова: (vl-browsefiles-in-directory-nested "c:\\documents" "*.dwg") |; (apply (function append) (cons (if (vl-directory-files path mask) (mapcar (function (lambda (x) (strcat (vl-string-right-trim "\" path) "\" x) ) ;_ end of lambda ) ;_ end of function (vl-directory-files path mask) ) ;_ end of mapcar ) ;_ if (mapcar (function (lambda (x) (vl-browsefiles-in-directory-nested (strcat (vl-string-right-trim "\" path) "\" x) mask ) ;_ end of vl-browsefiles-in-directory-nested ) ;_ end of lambda ) ;_ end of function (vl-remove ".." (vl-remove "." (vl-directory-files path nil -1)) ) ;_ end of vl-remove ) ;_ mapcar ) ;_ cons ) ;_ end of apply ) ;_ end of defun (if (not (vl-bb-ref '*kpblc-tip-of-the-day*)) (progn (setq files (vl-remove-if (function (lambda (x) (or (member x '("." "..")) (vl-file-directory-p x) (not (wcmatch (strcase (vl-filename-extension x)) ".HTM*")) ) ;_ end of or ) ;_ end of lambda ) ;_ end of function (vl-browsefiles-in-directory-nested path "*.*") ) ;_ end of vl-remove-if file (nth (fix (* (_dwgru-random) (length files))) files) ) ;_ end of setq (vla-launchbrowserdialog (vla-get-utility (vla-get-activedocument (vlax-get-acad-object))) file "Совет дня" "Открыть" file "" :vlax-false ) ;_ end of vla-LaunchBrowserDialog (vl-bb-set '*kpblc-tip-of-the-day* t) ) ;_ end of progn ) ;_ end of if ) ;_ end of defun (tip-of-the-day) |
Добавлю: внося минимальные изменения в код, можно добиться и показа "совета дня", и "поздравления", и чего угодно - хоть в alert'e, хоть в окне MSIE, хоть еще как.
Похожее
Размещено в Код LISP, Новости, Функции LISP · Метки: Команды AutoCAD, Разное
Лен, так дальше допиливать? Есть идея хранить все советы в отдельном текстовом файле, а показывать чуть ли не обычный алерт со случайно выбранным текстом из этого файла. Практически повтор варианта №4 ("Перечень поздравлений"), но с хранением текста не в коде.