1 | /* |
2 | * Legal Notice |
3 | * |
4 | * This document and associated source code (the "Work") is a part of a |
5 | * benchmark specification maintained by the TPC. |
6 | * |
7 | * The TPC reserves all right, title, and interest to the Work as provided |
8 | * under U.S. and international laws, including without limitation all patent |
9 | * and trademark rights therein. |
10 | * |
11 | * No Warranty |
12 | * |
13 | * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION |
14 | * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE |
15 | * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER |
16 | * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, |
17 | * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, |
18 | * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR |
19 | * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF |
20 | * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE. |
21 | * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, |
22 | * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT |
23 | * WITH REGARD TO THE WORK. |
24 | * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO |
25 | * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE |
26 | * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS |
27 | * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, |
28 | * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY, |
29 | * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT |
30 | * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD |
31 | * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. |
32 | * |
33 | * Contributors |
34 | * - Sergey Vasilevskiy |
35 | * - Doug Johnson |
36 | */ |
37 | |
38 | /* |
39 | * Class representing the News Item and News XRef tables. |
40 | */ |
41 | #ifndef NEWS_ITEM_AND_XREG_TABLE_H |
42 | #define NEWS_ITEM_AND_XREG_TABLE_H |
43 | |
44 | #include "EGenTables_common.h" |
45 | #include "CompanyTable.h" |
46 | |
47 | #include "input/DataFileManager.h" |
48 | |
49 | namespace TPCE { |
50 | |
51 | const int iNewsItemsPerCompany = 2; |
52 | const int iNewsItemMaxDaysAgo = 50; // how many days ago can a news item be dated |
53 | |
54 | const int iRNGSkipOneRowNews = 4 + cNI_ITEM_len; // number of RNG calls for one row |
55 | |
56 | typedef struct NEWS_ITEM_AND_XREF_ROW { |
57 | NEWS_ITEM_ROW news_item; |
58 | NEWS_XREF_ROW news_xref; |
59 | } * PNEWS_ITEM_AND_XREF_ROW; |
60 | |
61 | class CNewsItemAndXRefTable : public TableTemplate<NEWS_ITEM_AND_XREF_ROW> { |
62 | CCompanyTable m_CompanyTable; |
63 | const NewsDataFile_t &m_News; |
64 | const LastNameDataFile_t &m_LastNames; |
65 | CDateTime m_NewsBaseDate; |
66 | int m_iNewsItemsGeneratedForCompany; |
67 | TIdent m_iNewsCountForOneLoadUnit; |
68 | |
69 | void GenerateNewsItemHeadlineAndSummary(NEWS_ITEM_ROW &news_item) { |
70 | int iThreshold; |
71 | unsigned int iLen = 0; |
72 | const char *szWord; |
73 | |
74 | while (iLen < sizeof(news_item.NI_ITEM) - 1) { |
75 | iThreshold = m_rnd.RndIntRange(0, m_News.size() - 1); |
76 | |
77 | szWord = m_News[iThreshold].WORD_CSTR(); |
78 | |
79 | while (szWord && *szWord && (iLen < sizeof(news_item.NI_ITEM) - 1)) { |
80 | news_item.NI_ITEM[iLen++] = *szWord++; // copy one letter at a time |
81 | } |
82 | |
83 | if (iLen < sizeof(news_item.NI_ITEM) - 1) { |
84 | news_item.NI_ITEM[iLen++] = ' '; // add space at the end of a word |
85 | } |
86 | } |
87 | |
88 | news_item.NI_ITEM[iLen] = '\0'; // NULL terminate in case if the last |
89 | // word was copied only partially |
90 | |
91 | // Now copy the headline and summary from the generated item. |
92 | memcpy(news_item.NI_HEADLINE, news_item.NI_ITEM, sizeof(news_item.NI_HEADLINE) - 1); |
93 | // news_item.NI_HEADLINE will be zero-terminated because it is |
94 | // initialized to all 0s in TableTemplate constructor and the last |
95 | // character is not overwritten. |
96 | |
97 | // Now copy the headline and summary from the generated item. |
98 | memcpy(news_item.NI_SUMMARY, news_item.NI_ITEM, sizeof(news_item.NI_SUMMARY) - 1); |
99 | // news_item.NI_SUMMARY will be zero-terminated because it is |
100 | // initialized to all 0s in TableTemplate constructor and the last |
101 | // character is not overwritten. |
102 | } |
103 | |
104 | /* |
105 | * Reset the state for the next load unit. |
106 | * |
107 | * PARAMETERS: |
108 | * none. |
109 | * |
110 | * RETURNS: |
111 | * none. |
112 | */ |
113 | void InitNextLoadUnit() { |
114 | m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault, (RNGSEED)m_iLastRowNumber * iRNGSkipOneRowNews)); |
115 | |
116 | ClearRecord(); // this is needed for EGenTest to work |
117 | } |
118 | |
119 | public: |
120 | CNewsItemAndXRefTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer, |
121 | INT32 iHoursOfInitialTrades) |
122 | : m_CompanyTable(dfm, iCustomerCount, iStartFromCustomer), m_News(dfm.NewsDataFile()), |
123 | m_LastNames(dfm.LastNameDataFile()), m_iNewsItemsGeneratedForCompany(0) { |
124 | m_iLastRowNumber = iNewsItemsPerCompany * dfm.CompanyFile().CalculateStartFromCompany(iStartFromCustomer); |
125 | |
126 | // Go to the last day of initial trades. |
127 | // News items will be dated up to iNewsItemMaxDaysAgo days back from |
128 | // that day. |
129 | // |
130 | m_NewsBaseDate.Set(InitialTradePopulationBaseYear, InitialTradePopulationBaseMonth, |
131 | InitialTradePopulationBaseDay, InitialTradePopulationBaseHour, |
132 | InitialTradePopulationBaseMinute, InitialTradePopulationBaseSecond, |
133 | InitialTradePopulationBaseFraction); |
134 | m_NewsBaseDate.Add(iHoursOfInitialTrades / HoursPerWorkDay, 0, true); |
135 | |
136 | m_iNewsCountForOneLoadUnit = |
137 | dfm.CompanyFile().CalculateCompanyCount(iDefaultLoadUnitSize) * iNewsItemsPerCompany; |
138 | }; |
139 | |
140 | /* |
141 | * Generates all column values for the next row. |
142 | */ |
143 | bool GenerateNextRecord() { |
144 | int iAddDayNo, iAddMSec, iThreshold; |
145 | |
146 | // Reset RNG at Load Unit boundary, so that all data is repeatable. |
147 | // |
148 | if (m_iLastRowNumber % m_iNewsCountForOneLoadUnit == 0) { |
149 | InitNextLoadUnit(); |
150 | } |
151 | |
152 | // Generate NEWS_ITEM row |
153 | m_row.news_item.NI_ID = m_iLastRowNumber + 1; // row number starts from 0 |
154 | GenerateNewsItemHeadlineAndSummary(m_row.news_item); |
155 | iAddDayNo = m_rnd.RndIntRange(0, iNewsItemMaxDaysAgo); |
156 | iAddMSec = m_rnd.RndIntRange(0, MsPerDay); |
157 | m_row.news_item.NI_DTS = m_NewsBaseDate; // substruct from the base date |
158 | m_row.news_item.NI_DTS.Add((-1) * iAddDayNo, (-1) * iAddMSec); |
159 | |
160 | iThreshold = m_rnd.RndIntRange(0, m_LastNames.size() - 1); |
161 | strncpy(m_row.news_item.NI_AUTHOR, m_LastNames[iThreshold].NAME_CSTR(), sizeof(m_row.news_item.NI_AUTHOR)); |
162 | |
163 | iThreshold = m_rnd.RndIntRange(0, m_LastNames.size() - 1); |
164 | strncpy(m_row.news_item.NI_SOURCE, m_LastNames[iThreshold].NAME_CSTR(), sizeof(m_row.news_item.NI_SOURCE)); |
165 | |
166 | // Generate NEWS_XREF row |
167 | m_row.news_xref.NX_NI_ID = m_row.news_item.NI_ID; |
168 | m_row.news_xref.NX_CO_ID = m_CompanyTable.GetCurrentCO_ID(); |
169 | |
170 | ++m_iNewsItemsGeneratedForCompany; |
171 | |
172 | ++m_iLastRowNumber; |
173 | |
174 | if (m_iNewsItemsGeneratedForCompany >= iNewsItemsPerCompany) { |
175 | m_bMoreRecords = m_CompanyTable.GenerateNextCO_ID(); |
176 | m_iNewsItemsGeneratedForCompany = 0; |
177 | } else { |
178 | m_bMoreRecords = true; // need to generate more rows for at least |
179 | // the current company |
180 | } |
181 | |
182 | return (MoreRecords()); |
183 | // return (m_iLastRowNumber < 10); |
184 | }; |
185 | |
186 | const NEWS_ITEM_ROW &GetNewsItemRow() { |
187 | return m_row.news_item; |
188 | } |
189 | const NEWS_XREF_ROW &GetNewsXRefRow() { |
190 | return m_row.news_xref; |
191 | } |
192 | }; |
193 | |
194 | } // namespace TPCE |
195 | |
196 | #endif // NEWS_ITEM_AND_XREG_TABLE_H |
197 | |