(defvar *password-judge-list* nil)
(defvar *password-list* (list "passw0rd" "abc123" "qwerty"))
(defvar *word-list* (list "password" "cat" "baseball"))
(defmacro push-password-judge (var test judge reason)
`(push #'(lambda (,var) (if ,test (values ,judge ,reason) :passed)) *password-judge-list*))
(push-password-judge p (<= (length p) 5) :bad :too-short)
(push-password-judge p (loop for prev-c = nil then c
for c across p
for n = 0 then (if (eql c prev-c) (1+ n) 1)
when (= n 3) do (return t)
finally (return nil))
:bad
:consecutive-three-letter)
;;;; regular-sequence, not implemented
(push-password-judge p (member p *password-list* :test #'string=) :bad :same-password)
(push-password-judge p (member p *word-list* :test #'string=) :bad :common-word)
(push-password-judge p (loop for w in *word-list*
when (search w p) do (return t)
finally (return nil))
:not-good
:contains-common-word)
(push-password-judge p (every #'alpha-char-p p) :not-good :all-alpha)
(push-password-judge p (every #'digit-char-p p) :bad :all-digit)
;;;; looks-date, not implemented
(defun judge-password (p)
(let ((judge :passed)
(reasons nil))
(dolist (judge-fn *password-judge-list*)
(multiple-value-bind (j r) (funcall judge-fn p)
(when r (push r reasons))
(when (or (eq judge :passed)
(and (eq judge :not-good) (eq j :bad)))
(setf judge j))))
(values judge reasons)))
(defvar *ps* (list "ac" "3AAA1567" "passw0rd" "baseball" "a4cat7R" "kreplm" "473546"))
(dolist (p *ps*)
(multiple-value-bind (j r) (judge-password p)
(if (eq j :passed)
(format t "~a:~a~%" p j)
(format t "~a:~a ~a~%" p j r))))