PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/Kumbia/Linguistics/Linguistics.php

http://kumbia-enterprise.googlecode.com/
PHP | 462 lines | 294 code | 23 blank | 145 comment | 75 complexity | 911759d978f7b35ca6fdbf61cec85e02 MD5 | raw file
  1. <?php
  2. /**
  3. * Kumbia Enterprise Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the New BSD License that is bundled
  8. * with this package in the file docs/LICENSE.txt.
  9. *
  10. * If you did not receive a copy of the license and are unable to
  11. * obtain it through the world-wide-web, please send an email
  12. * to license@loudertechnology.com so we can send you a copy immediately.
  13. *
  14. * @category Kumbia
  15. * @package Linguistics
  16. * @copyright Copyright (c) 2008-2010 Louder Technology COL. (http://www.loudertechnology.com)
  17. * @license New BSD License
  18. */
  19. /**
  20. * Linguistics
  21. *
  22. * Permite efectuar diversas operaciones lingüisticas basadas en localización
  23. *
  24. * @category Kumbia
  25. * @package Linguistics
  26. * @copyright Copyright (c) 2008-2010 Louder Technology COL. (http://www.loudertechnology.com)
  27. * @license New BSD License
  28. */
  29. class Linguistics {
  30. /**
  31. * Valor a convertir
  32. *
  33. * @var integer
  34. */
  35. private static $_value = 0;
  36. /**
  37. * Estado de la conversion
  38. *
  39. * @var string
  40. */
  41. private static $_state = '';
  42. /**
  43. * Localización usada para realizar las operaciones
  44. *
  45. * @var Locale
  46. */
  47. private $_locale;
  48. /**
  49. * Reglas de linguisticas para la localización activa
  50. *
  51. * @var LinguisticsEs
  52. */
  53. private $_rules;
  54. /**
  55. * Constructor de Linguistics
  56. *
  57. * @param Locale $locale
  58. */
  59. public function __construct($locale=null){
  60. if($locale==null){
  61. $locale = Locale::getApplication();
  62. }
  63. $this->setLocale($locale);
  64. }
  65. /**
  66. * Establece la localización para la lingüistica
  67. *
  68. * @param string $language
  69. */
  70. public function setLocale($locale){
  71. if(is_string($locale)){
  72. $this->_locale = new Locale($locale);
  73. } else {
  74. $this->_locale = $locale;
  75. }
  76. $language = $this->_locale->getLanguage();
  77. $className = 'Linguistics'.ucfirst($language);
  78. if(class_exists($className, false)==false){
  79. $path = 'Library/Kumbia/Linguistics/Rules/'.$className.'.php';
  80. if(file_exists($path)){
  81. require $path;
  82. } else {
  83. throw new LinguisticsException('No existen reglas de localización para el idioma '.$language);
  84. }
  85. }
  86. $this->_rules = new $className($this->_locale);
  87. }
  88. /**
  89. * Pluralizar una palabra
  90. *
  91. * @param $word
  92. * @return string
  93. */
  94. public function pluralize($word){
  95. return $this->_rules->pluralize($word);
  96. }
  97. /**
  98. * Indica si una palabra tiene genero femenino
  99. *
  100. * @param $word
  101. * @return string
  102. */
  103. public function isFemale($word){
  104. return $this->_rules->isFemale($word);
  105. }
  106. /**
  107. * Recibe una palabra en singular y genera el infinitivo "a" según su genero
  108. *
  109. * @param string $singleWord
  110. * @package boolean $isPlural
  111. */
  112. public function a($word, $isPlural=false){
  113. return $this->_rules->applyArticle('indefinite', $word, $isPlural);
  114. }
  115. /**
  116. * Recibe una palabra y genera el artículo "el", "la", "los", "las" según su genero
  117. *
  118. * @param string $singleWord
  119. * @package boolean $isPlural
  120. */
  121. public function the($word, $isPlural=false){
  122. return $this->_rules->applyArticle('definite', $word, $isPlural);
  123. }
  124. /**
  125. * Cambiar a genero masculino una palabra singular
  126. *
  127. * @param string $word
  128. */
  129. public function toMale($word){
  130. return $this->_rules->toMale($word);
  131. }
  132. /**
  133. * Cambiar a genero femenino una palabra en singular
  134. *
  135. * @param string $word
  136. */
  137. public function toFemale($word){
  138. return $this->_rules->toFemale($word);
  139. }
  140. /**
  141. * Realiza una conjunción de valores
  142. *
  143. * @param mixed $values
  144. */
  145. public function getConjunction($values, $indefinite=false){
  146. if(!is_array($values)){
  147. $values = explode(' ', $values);
  148. }
  149. $values = array_count_values($values);
  150. $phrase = array();
  151. foreach($values as $word => $number){
  152. if($number==1){
  153. if($indefinite){
  154. $phrase[] = $this->a($word);
  155. } else {
  156. $phrase[] = $this->the($word);
  157. }
  158. } else {
  159. $phrase[] = i18n::strtolower(self::getNumberToWords($number)).' '.$this->pluralize($word);
  160. }
  161. }
  162. return $this->_locale->getConjunction($phrase);
  163. }
  164. /**
  165. * Obtiene la cuatificación para "muchos"
  166. *
  167. * @param string $word
  168. * @return string
  169. */
  170. public function getSeveral($word){
  171. return $this->_rules->getSeveral($word);
  172. }
  173. /**
  174. * Obtiene la cuatificación para "ninguno" ó "nada"
  175. *
  176. * @param string $word
  177. * @return string
  178. */
  179. public function getNoQuantity($word){
  180. return $this->_rules->getNoQuantity($word);
  181. }
  182. /**
  183. * Devuelve un valor cuantificado
  184. *
  185. * @param int $value
  186. * @return number
  187. */
  188. public function getQuantification($value, $substantive){
  189. $quantities = $this->_locale->getQuantities();
  190. if($value>=0){
  191. if($value==0){
  192. return $this->getNoQuantity($substantive);
  193. } else {
  194. if($value==1){
  195. return $this->a($substantive);
  196. } else {
  197. if($value<29){
  198. return $this->getSeveral($substantive);
  199. } else {
  200. $prepositions = $this->_locale->getLinguisticPrepositions();
  201. if($value<199){
  202. return $quantities['dozens'].' '.$prepositions['of'].' '.$this->pluralize($substantive);
  203. } else {
  204. if($value<1999){
  205. return $quantities['hundreds'].' '.$prepositions['of'].' '.$this->pluralize($substantive);
  206. } else {
  207. if($value<19999){
  208. return $quantities['thousands'].' '.$prepositions['of'].' '.$this->pluralize($substantive);
  209. } else {
  210. return $quantities['millions'].' '.$prepositions['of'].' '.$this->pluralize($substantive);
  211. }
  212. }
  213. }
  214. }
  215. }
  216. }
  217. return '';
  218. } else {
  219. if($value==-1){
  220. return $quantities['minus'].' '.$this->a($substantive);
  221. } else {
  222. return $quantities['minus'].' '.abs($value).' '.$substantive;
  223. }
  224. }
  225. }
  226. /**
  227. * Las siguientes funciones son utilizadas para la generación
  228. * de versiones escritas de numeros
  229. *
  230. * @param numeric $a
  231. * @return string
  232. * @static
  233. */
  234. private static function valueNumber($a){
  235. if($a<=21){
  236. switch ($a){
  237. case 1:
  238. if(self::$_state=='DEC'||self::$_state==''){
  239. return 'UN';
  240. } else {
  241. return 'UNO';
  242. }
  243. case 2: return 'DOS';
  244. case 3: return 'TRES';
  245. case 4: return 'CUATRO';
  246. case 5: return 'CINCO';
  247. case 6: return 'SEIS';
  248. case 7: return 'SIETE';
  249. case 8: return 'OCHO';
  250. case 9: return 'NUEVE';
  251. case 10: return 'DIEZ';
  252. case 11: return 'ONCE';
  253. case 12: return 'DOCE';
  254. case 13: return 'TRECE';
  255. case 14: return 'CATORCE';
  256. case 15: return 'QUINCE';
  257. case 16: return 'DIECISEIS';
  258. case 17: return 'DIECISIETE';
  259. case 18: return 'DIECIOCHO';
  260. case 19: return 'DIECINUEVE';
  261. case 20: return 'VEINTE';
  262. case 21:
  263. if(self::$_state==''){
  264. return 'VENTIUNO';
  265. } else {
  266. return 'VENTIUN';
  267. }
  268. }
  269. } else {
  270. if($a<=99){
  271. self::$_state = 'DEC';
  272. if($a>=22&&$a<=29){
  273. return 'VENTI'.self::valueNumber($a % 10);
  274. }
  275. if($a==30){
  276. return 'TREINTA';
  277. }
  278. if($a>=31&&$a<=39){
  279. return 'TREINTA Y '.self::valueNumber($a % 10);
  280. }
  281. if($a==40){
  282. return 'CUARENTA';
  283. }
  284. if($a>=41&&$a<=49){
  285. return 'CUARENTA Y '.self::valueNumber($a % 10);
  286. }
  287. if($a==50){
  288. return 'CINCUENTA';
  289. }
  290. if($a>=51&&$a<=59){
  291. return 'CINCUENTA Y '.self::valueNumber($a % 10);
  292. }
  293. if($a==60){
  294. return 'SESENTA';
  295. }
  296. if($a>=61&&$a<=69){
  297. return 'SESENTA Y '.self::valueNumber($a % 10);
  298. }
  299. if($a==70) {
  300. return 'SETENTA';
  301. }
  302. if($a>=71&&$a<=79){
  303. return 'SETENTA Y '.self::valueNumber($a % 10);
  304. }
  305. if($a==80){
  306. return 'OCHENTA';
  307. }
  308. if($a>=81&&$a<=89){
  309. return 'OCHENTA Y '.self::valueNumber($a % 10);
  310. }
  311. if($a==90){
  312. return 'NOVENTA';
  313. }
  314. if($a>=91&&$a<=99){
  315. return 'NOVENTA Y '.self::valueNumber($a % 10);
  316. }
  317. } else {
  318. self::$_state = 'CEN';
  319. if($a==100){
  320. return 'CIEN';
  321. }
  322. if($a>=101&&$a<=199){
  323. return 'CIENTO '.self::valueNumber($a % 100);
  324. }
  325. if($a>=200&&$a<=299){
  326. return 'DOSCIENTOS '.self::valueNumber($a % 100);
  327. }
  328. if($a>=300&&$a<=399){
  329. return 'TRECIENTOS '.self::valueNumber($a % 100);
  330. }
  331. if($a>=400&&$a<=499){
  332. return 'CUATROCIENTOS '.self::valueNumber($a % 100);
  333. }
  334. if($a>=500&&$a<=599){
  335. return 'QUINIENTOS '.self::valueNumber($a % 100);
  336. }
  337. if($a>=600&&$a<=699){
  338. return 'SEICIENTOS '.self::valueNumber($a % 100);
  339. }
  340. if($a>=700&&$a<=799){
  341. return 'SETECIENTOS '.self::valueNumber($a % 100);
  342. }
  343. if($a>=800&&$a<=899){
  344. return 'OCHOCIENTOS '.self::valueNumber($a % 100);
  345. }
  346. if($a>=901&&$a<=999){
  347. return 'NOVECIENTOS '.self::valueNumber($a % 100);
  348. }
  349. }
  350. }
  351. }
  352. /**
  353. * Genera una cadena de millones
  354. *
  355. * @param double $a
  356. * @return string
  357. * @static
  358. */
  359. private static function millions($number){
  360. self::$_state = 'MILL';
  361. $number = LocaleMath::div($number, '1000000');
  362. if($number==1){
  363. return 'UN MILLON ';
  364. } else {
  365. if(LocaleMath::cmp($number, '1000')>=0){
  366. $mod = LocaleMath::mod($number, '1000');
  367. $value = self::miles(LocaleMath::sub($number, $mod));
  368. if($mod>0){
  369. $value.= self::valueNumber($mod);
  370. }
  371. $value.=' MILLONES ';
  372. } else {
  373. $value = self::valueNumber($number).' MILLONES ';
  374. }
  375. self::$_state = 'MILL';
  376. return $value;
  377. }
  378. }
  379. /**
  380. * Genera una cadena de miles
  381. *
  382. * @param double $a
  383. * @return string
  384. * @static
  385. */
  386. private static function miles($number){
  387. self::$_state = 'MIL';
  388. $number = LocaleMath::div($number, '1000');
  389. if($number==1){
  390. return 'MIL';
  391. } else {
  392. return self::valueNumber($number).'MIL ';
  393. }
  394. }
  395. /**
  396. * Escribe en letras un monto numérico
  397. *
  398. * @param numeric $valor
  399. * @param string $moneda
  400. * @param string $centavos
  401. * @return string
  402. * @static
  403. */
  404. static public function getNumberToWords($valor, $moneda='', $centavos=''){
  405. self::$_value = $valor;
  406. $a = $valor;
  407. $p = $moneda;
  408. $c = $centavos;
  409. $val = '';
  410. $v = $a;
  411. $a = LocaleMath::round($a, 0);
  412. $d = (float) LocaleMath::round($v-$a, 2);
  413. if(LocaleMath::cmp($a, '1000000')>=0){
  414. $mod = LocaleMath::mod($a, '1000000');
  415. $val.= self::millions(LocaleMath::sub($a, $mod));
  416. $a = $mod;
  417. }
  418. if(LocaleMath::cmp($a, '1000')>=0){
  419. $mod = LocaleMath::mod($a, '1000');
  420. $val.= self::miles(LocaleMath::sub($a, $mod));
  421. $a = $mod;
  422. }
  423. $rval = self::valueNumber($a);
  424. if($rval==''){
  425. if(in_array(self::$_state, array('MILL', 'MMILL'))){
  426. $val.= 'DE '.strtoupper($p).' ';
  427. } else {
  428. $val.= strtoupper($p).' ';
  429. }
  430. } else {
  431. $val.= $rval.' '.strtoupper($p).' ';
  432. }
  433. if($d>0){
  434. $d*=100;
  435. $val.= ' CON '.self::valueNumber($d).' '.$c.' ';
  436. }
  437. return trim($val);
  438. }
  439. }