(in-package :wine-matrix/data-source) (defgeneric temperature (source) (:documentation "Return the temperature reported by SOURCE. This temperature is reported as as a list of the form (TEMPERATURE UNITS).")) (defgeneric humidity (source) (:documentation "Return the humidity reported by SOURCE. This temperature is reported as a list of the form (HUMIDITY UNITS).")) (defgeneric rack (source) (:documentation "Return the state of the rack reported by SOURCE. The result is a list of lists where each element is either nil or t depending on weather a bottle exists in that spot.")) (defgeneric user-options (source) (:documentation "Return a list of user configurable options. This should be a list with each element being a list of the form (SLOT PARSER NAME). NAME is a string and should be the name to display to the user. It will be processed with `string-capitalize'. PARSER is a function that takes a string an returns the parsed value. If the string is invalid. PARSER should signal an `error'. SLOT is the slot to set when the value should be updated.")) (defgeneric unit-to-kelvin (unit temp) (:documentation "Convert TEMP in unit UNIT to kelvin.")) (defmethod unit-to-kelvin ((unit (eql 'kelvin)) temp) temp) (defmethod unit-to-kelvin ((unit (eql 'celsius)) temp) ;; add 273.15 (+ temp 273 (/ 3 20))) (defmethod unit-to-kelvin ((unit (eql 'fahrenheit)) temp) (unit-to-kelvin 'celsius (* (- temp 32) (/ 5 9)))) (defgeneric kelvin-to-unit (unit temp) (:documentation "Convert TEMP which is in unit UNIT to kelvin.")) (defmethod kelvin-to-unit ((unit (eql 'kelvin)) temp) temp) (defmethod kelvin-to-unit ((unit (eql 'celsius)) temp) ;; subtract 273.15 (- temp (+ 273 (/ 3 20)))) (defmethod kelvin-to-unit ((unit (eql 'fahrenheit)) temp) (+ (* (kelvin-to-unit 'celsius temp) (/ 9 5)) 32)) (defun temperature-as (new-unit temp) "Convert TEMP, which is of the form (VALUE UNIT), to NEW-UNIT." (kelvin-to-unit new-unit (unit-to-kelvin (second temp) (first temp))))