1 /**
2 * userphrase.c
3 *
4 * Copyright (c) 1999, 2000, 2001
5 * Lu-chuan Kung and Kang-pen Chen.
6 * All rights reserved.
7 *
8 * Copyright (c) 2004
9 * libchewing Core Team. See ChangeLog for details.
10 *
11 * See the file "COPYING" for information on usage and redistribution
12 * of this file.
13 */
14
15 #include <stdlib.h>
16 #include <time.h>
17 #include <string.h>
18
19 #include "global.h"
20 #include "hash.h"
21 #include "dict.h"
22 #include "private.h"
23
24 extern int chewing_lifetime;
25 static HASH_ITEM *pItemLast;
26
DeltaFreq(int recentTime)27 int DeltaFreq( int recentTime )
28 {
29 int diff;
30
31 diff = ( chewing_lifetime - recentTime );
32
33 if ( diff < 1000 )
34 return ( 1500 - diff ); /* 1500 ~ 500 */
35 if ( diff < 2000 )
36 return ( 500 ); /* 500 ~ 500 */
37 if ( diff < 3000 )
38 return ( 2500 - diff ); /* 500 ~ -500 */
39 return ( -500 ); /* -500 forever */
40 }
41
42 /* load the orginal frequency from the static dict */
LoadOriginalFreq(const uint16 phoneSeq[],const char wordSeq[],int len)43 int LoadOriginalFreq( const uint16 phoneSeq[], const char wordSeq[], int len )
44 {
45 int pho_id;
46 int retval;
47 Phrase *phrase = ALC( Phrase, 1 );
48
49 pho_id = TreeFindPhrase( 0, len - 1, phoneSeq );
50 if ( pho_id != -1 ) {
51 GetPhraseFirst( phrase, pho_id );
52 do {
53 /* find the same phrase */
54 if ( ! memcmp(
55 phrase->phrase,
56 wordSeq,
57 len * 2 * sizeof( char ) ) ) {
58 retval = phrase->freq;
59 free( phrase );
60 return retval;
61 }
62 } while ( GetPhraseNext( phrase ) );
63 }
64
65 return FREQ_INIT_VALUE;
66 }
67
68 /* find the maximum frequency of the same phrase */
LoadMaxFreq(const uint16 phoneSeq[],int len)69 int LoadMaxFreq( const uint16 phoneSeq[], int len )
70 {
71 int pho_id;
72 Phrase *phrase = ALC( Phrase, 1 );
73 int maxFreq = FREQ_INIT_VALUE;
74 UserPhraseData *uphrase;
75
76 pho_id = TreeFindPhrase( 0, len - 1, phoneSeq );
77 if ( pho_id != -1 ) {
78 GetPhraseFirst( phrase, pho_id );
79 do {
80 if ( phrase->freq > maxFreq )
81 maxFreq = phrase->freq;
82 } while( GetPhraseNext( phrase ) );
83 }
84 free( phrase );
85
86 uphrase = UserGetPhraseFirst( phoneSeq );
87 while ( uphrase ) {
88 if ( uphrase->userfreq > maxFreq )
89 maxFreq = uphrase->userfreq;
90 uphrase = UserGetPhraseNext( phoneSeq );
91 }
92
93 return maxFreq;
94 }
95
96 /* compute the new updated freqency */
UpdateFreq(int freq,int maxfreq,int origfreq,int deltatime)97 int UpdateFreq( int freq, int maxfreq, int origfreq, int deltatime )
98 {
99 int delta;
100
101 /* Short interval */
102 if ( deltatime < 4000 ) {
103 delta = ( freq >= maxfreq ) ?
104 min(
105 ( maxfreq - origfreq ) / 5 + 1,
106 SHORT_INCREASE_FREQ ) :
107 max(
108 ( maxfreq - origfreq ) / 5 + 1,
109 SHORT_INCREASE_FREQ );
110 return min( freq + delta, MAX_ALLOW_FREQ );
111 }
112 /* Medium interval */
113 else if ( deltatime < 50000 ) {
114 delta = ( freq >= maxfreq ) ?
115 min(
116 ( maxfreq - origfreq ) / 10 + 1,
117 MEDIUM_INCREASE_FREQ ) :
118 max(
119 ( maxfreq - origfreq ) / 10 + 1,
120 MEDIUM_INCREASE_FREQ );
121 return min( freq + delta, MAX_ALLOW_FREQ );
122 }
123 /* long interval */
124 else {
125 delta = max( ( freq - origfreq ) / 5, LONG_DECREASE_FREQ );
126 return max( freq - delta, origfreq );
127 }
128 }
129
UserUpdatePhrase(const uint16 phoneSeq[],const char wordSeq[])130 int UserUpdatePhrase( const uint16 phoneSeq[], const char wordSeq[] )
131 {
132 HASH_ITEM *pItem;
133 UserPhraseData data;
134 int len;
135
136 len = strlen( wordSeq ) / 2;
137 pItem = HashFindEntry( phoneSeq, wordSeq );
138 if ( ! pItem ) {
139 if ( ! AlcUserPhraseSeq( &data, len ) ) {
140 return USER_UPDATE_FAIL;
141 }
142
143 memcpy( data.phoneSeq, phoneSeq, len * sizeof( phoneSeq[ 0 ] ) );
144 data.phoneSeq[ len ] = 0;
145 strcpy( data.wordSeq, wordSeq );
146
147 /* load initial freq */
148 data.origfreq = LoadOriginalFreq( phoneSeq, wordSeq, len );
149 data.maxfreq = LoadMaxFreq( phoneSeq, len );
150
151 data.userfreq = data.origfreq;
152 data.recentTime = chewing_lifetime;
153 pItem = HashInsert( &data );
154 HashModify( pItem );
155 return USER_UPDATE_INSERT;
156 }
157 else {
158 pItem->data.maxfreq = LoadMaxFreq( phoneSeq, len );
159 pItem->data.userfreq = UpdateFreq(
160 pItem->data.userfreq,
161 pItem->data.maxfreq,
162 pItem->data.origfreq,
163 chewing_lifetime - pItem->data.recentTime );
164 pItem->data.recentTime = chewing_lifetime;
165 HashModify( pItem );
166 return USER_UPDATE_MODIFY;
167 }
168 }
169
UserGetPhraseFirst(const uint16 phoneSeq[])170 UserPhraseData *UserGetPhraseFirst( const uint16 phoneSeq[] )
171 {
172 pItemLast = HashFindPhonePhrase( phoneSeq, NULL );
173 if ( ! pItemLast )
174 return NULL;
175 return &( pItemLast->data );
176 }
177
UserGetPhraseNext(const uint16 phoneSeq[])178 UserPhraseData *UserGetPhraseNext( const uint16 phoneSeq[] )
179 {
180 pItemLast = HashFindPhonePhrase( phoneSeq, pItemLast );
181 if ( ! pItemLast )
182 return NULL;
183 return &( pItemLast->data );
184 }
185
186