1 /* PSPP - RANK. -*-c-*-
3 Copyright (C) 2005 Free Software Foundation, Inc.
4 Author: John Darrington 2005
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "sort-criteria.h"
25 #include <data/dictionary.h>
26 #include <data/procedure.h>
27 #include <data/variable.h>
28 #include <language/command.h>
29 #include <language/stats/sort-criteria.h>
30 #include <libpspp/compiler.h>
31 #include <math/sort.h>
34 #define _(msgid) gettext (msgid)
50 +missing=miss:!exclude/include.
73 struct variable **destvars;
74 struct variable *srcvar;
78 static struct rank_spec *rank_specs;
79 static size_t n_rank_specs;
81 static struct sort_criteria *sc;
83 static struct variable **group_vars;
84 static size_t n_group_vars;
86 static struct cmd_rank cmd;
98 if ( !parse_rank(&cmd, NULL) )
102 for (i = 0 ; i < sc->crit_cnt ; ++i )
104 struct sort_criterion *crit = &sc->crits[i];
106 printf("Dir: %d; Index: %d\n", crit->dir, crit->fv);
109 for (i = 0 ; i < n_group_vars ; ++i )
110 printf("Group var: %s\n",group_vars[0]->name);
112 for (i = 0 ; i < n_rank_specs ; ++i )
115 printf("Ranks spec %d; Func: %d\n",i, rank_specs[i].rfunc);
117 for (j=0; j < sc->crit_cnt ; ++j )
118 printf("Dest var is \"%s\"\n", rank_specs[i].destvars[j]->name);
125 for (i = 0 ; i < n_rank_specs ; ++i )
127 free(rank_specs[i].destvars);
132 sort_destroy_criteria(sc);
139 /* Parser for the variables sub command
140 Returns 1 on success */
142 rank_custom_variables(struct cmd_rank *cmd UNUSED, void *aux UNUSED)
144 static const int terminators[2] = {T_BY, 0};
148 if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
152 sc = sort_parse_criteria (default_dict, 0, 0, 0, terminators);
154 if ( lex_match(T_BY) )
156 if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL))
161 if (!parse_variables (default_dict, &group_vars, &n_group_vars,
162 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
173 /* Return a name for a new variable which ranks the variable VAR_NAME,
174 according to the ranking function F.
175 If IDX is non zero, then IDX is used as a disambiguating number.
176 FIXME: This is not very robust.
179 new_variable_name(const char *ranked_var_name, enum RANK_FUNC f, int idx)
181 static char new_name[SHORT_NAME_LEN + 1];
182 char temp[SHORT_NAME_LEN + 1];
190 strcpy(new_name,"R");
196 strcpy(new_name,"N");
201 strcpy(new_name,"P");
205 strcpy(new_name,"S");
213 strncat(new_name, ranked_var_name, 7);
217 strncpy(temp, ranked_var_name, 3);
218 snprintf(new_name, SHORT_NAME_LEN, "%s%03d", temp, idx);
224 /* Parse the [/rank INTO var1 var2 ... varN ] clause */
226 parse_rank_function(struct cmd_rank *cmd UNUSED, enum RANK_FUNC f)
228 static const struct fmt_spec f8_2 = {FMT_F, 8, 2};
232 rank_specs = xnrealloc(rank_specs, n_rank_specs, sizeof *rank_specs);
233 rank_specs[n_rank_specs - 1].rfunc = f;
235 rank_specs[n_rank_specs - 1].destvars =
236 xcalloc (sc->crit_cnt, sizeof (struct variable *));
238 if (lex_match_id("INTO"))
240 struct variable *destvar;
242 while( token == T_ID )
245 if ( dict_lookup_var (default_dict, tokid) != NULL )
247 msg(SE, _("Variable %s already exists."), tokid);
250 if ( var_count > sc->crit_cnt )
252 msg(SE, _("Too many variables in INTO clause."));
256 destvar = dict_create_var (default_dict, tokid, 0);
259 destvar->print = destvar->write = f8_2;
262 rank_specs[n_rank_specs - 1].destvars[var_count - 1] = destvar ;
269 /* Allocate rank variable names to all those which haven't had INTO
270 variables assigned */
271 while (var_count < sc->crit_cnt)
274 struct variable *destvar ;
275 const struct variable *v = dict_get_var(default_dict,
276 sc->crits[var_count].fv);
281 new_name = new_variable_name(v->name, f, idx);
283 destvar = dict_create_var (default_dict, new_name, 0);
287 } while( !destvar ) ;
289 destvar->print = destvar->write = f8_2;
291 rank_specs[n_rank_specs - 1].destvars[var_count] = destvar ;
301 rank_custom_rank(struct cmd_rank *cmd, void *aux UNUSED )
303 return parse_rank_function(cmd, RANK);
307 rank_custom_normal(struct cmd_rank *cmd, void *aux UNUSED )
309 return parse_rank_function(cmd, NORMAL);
313 rank_custom_percent(struct cmd_rank *cmd, void *aux UNUSED )
315 return parse_rank_function(cmd, NORMAL);
319 rank_custom_rfraction(struct cmd_rank *cmd, void *aux UNUSED )
321 return parse_rank_function(cmd, RFRACTION);
325 rank_custom_proportion(struct cmd_rank *cmd, void *aux UNUSED )
327 return parse_rank_function(cmd, PROPORTION);
331 rank_custom_n(struct cmd_rank *cmd, void *aux UNUSED )
333 return parse_rank_function(cmd, N);
337 rank_custom_savage(struct cmd_rank *cmd, void *aux UNUSED )
339 return parse_rank_function(cmd, SAVAGE);
344 rank_custom_ntiles(struct cmd_rank *cmd, void *aux UNUSED )
346 if ( lex_force_match('(') )
348 if ( lex_force_int() )
351 lex_force_match(')');
359 return parse_rank_function(cmd, NTILES);