text:
import com.datastax.driver.core.Row;
import com.google.common.net.HttpHeaders;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.io.DefaultIoCallback;
import io.undertow.io.Sender;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.RoutingHandler;
import io.undertow.server.handlers.PredicateHandler;
import io.undertow.server.handlers.accesslog.AccessLogHandler;
import io.undertow.server.handlers.accesslog.DefaultAccessLogReceiver;
import io.undertow.server.handlers.proxy.SimpleProxyClientProvider;
import io.undertow.util.*;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONNavi;
import net.minidev.json.JSONObject;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static io.undertow.Handlers.routing;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class MHAClinicalAPI {
    public static String readQueryFromFile(String file_name) {
        try (InputStream ins = ClassLoader.getSystemResourceAsStream("Queries/" + file_name)) {
            BufferedReader br = new BufferedReader(new InputStreamReader(ins));
            return br.lines().collect(joining("\n"));
        } catch (IOException ex) {
            ex.printStackTrace();
            return "";
        }
    }

    static DICOMClient dicomClient;
    static SPARQLClient sparqlClient;

    private static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
        CompletableFuture<Void> allDoneFuture =
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
        return allDoneFuture.thenApply(v ->
                futures.stream().
                        map(CompletableFuture::join).
                        collect(Collectors.<T>toList()));
    }

    public static void get_dcm_series(final DICOMClient dcmClient, final String series_id, HttpServerExchange exchange) {

        try {
            final Path tempDirectory = Files.createTempDirectory("mha-series-");
            dcmClient.get_series_async(series_id, tempDirectory.toFile())
                    .thenAcceptAsync(fileNames -> {
                        if (fileNames.isEmpty()) {
                            safelyDeleteFileOrDir(tempDirectory);
                            exchange.setStatusCode(StatusCodes.NOT_FOUND);
                            exchange.getResponseSender().send(String.format("Series <%s> does not contain any instances!\n", series_id));
                            exchange.endExchange();
                            return;
                        }

                        System.out.printf("<%s> Got %d instances\n", Thread.currentThread().getName(), fileNames.size());

                        try {
                            final Path tempFile = Paths.get(System.getProperty("java.io.tmpdir"), "mha-" + UUID.randomUUID().toString() + ".zip");
                            ZipUtils.zipDir(tempDirectory, tempFile);
                            //System.out.println(Thread.currentThread().getName() + " Check zip file " + tempFile);

                            exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/zip");
                            exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, tempFile.toFile().length());
                            exchange.getResponseHeaders().put(HttpString.tryFromString("Content-Disposition"),
                                    String.format("attachment; filename=series-%s.zip", series_id));
                            exchange.getResponseSender().transferFrom(FileChannel.open(tempFile), new DefaultIoCallback() {
                                @Override
                                public void onComplete(HttpServerExchange httpServerExchange, Sender sender) {
                                    safelyDeleteFileOrDir(tempDirectory);
                                    safelyDeleteFileOrDir(tempFile);
                                    super.onComplete(exchange, sender);
                                }

                                @Override
                                public void onException(final HttpServerExchange exchange, final Sender sender, final IOException exception) {
                                    safelyDeleteFileOrDir(tempDirectory);
                                    safelyDeleteFileOrDir(tempFile);
                                    super.onException(exchange, sender, exception);
                                }

                            });
                        } catch (Exception e) {
                            e.printStackTrace();
                            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                            exchange.endExchange();
                        }
                    });

        } catch (IOException e) {
            e.printStackTrace();
            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
            exchange.endExchange();
        }

    }

    private static void safelyDeleteFileOrDir(Path path) {
        try {
            if (Files.isDirectory(path))
                FileUtils.deleteRecursive(path);
            else
                Files.delete(path);
        } catch (IOException e) {
            // ignored
        }
    }

    @Deprecated
    public static void ask_cassandra(final String user, final String baseURI, HttpServerExchange exchange) {

        Map<String, Deque<String>> params = exchange.getQueryParameters();
        final LocalDate from = params.containsKey("from")
                ? LocalDate.parse(params.get("from").getFirst(), DateTimeFormatter.ISO_LOCAL_DATE)
                : LocalDate.MIN;
        final LocalDate to = params.containsKey("to")
                ? LocalDate.parse(params.get("to").getFirst(), DateTimeFormatter.ISO_LOCAL_DATE)
                : LocalDate.MAX;

        System.out.printf("[%s] GET pat summary of %s for period [%s, %s]\n",
                ZonedDateTime.now().toString(), user, from, to);

        CompletableFuture<UUID> pat_sum_uuid = CassandraClient.DB.executeAsync("select inserted from patient_summary where mha_uid=? limit 1", user)
                .thenApplyAsync(rows -> {
                    //System.out.println("uuid " + Thread.currentThread().getName());
                    final Row one = rows.one();
                    if (one == null) {
                        exchange.setStatusCode(StatusCodes.NOT_FOUND);
                        // exchange.endExchange();
                        throw new RuntimeException("Given patient ssn was not found");
                    }
                    return one.getUUID("inserted");
                });

        CompletableFuture<JSONArray> problems = pat_sum_uuid
                .thenCompose(uuid -> CassandraClient.DB.executeAsync("select * from problems where mha_uid=? and inserted=?", user, uuid))
                .thenApply(rows -> {
                    //System.out.println("problems " + Thread.currentThread().getName());
                    List<JSONObject> list = rows.all().stream().map(row -> {
                        JSONObject problem = new JSONObject();
                        problem.put("code", row.getString("code"));
                        problem.put("code_system", row.getString("code_system"));
                        problem.put("title", row.getString("title"));
                        return problem;
                    }).collect(toList());
                    JSONArray probs = new JSONArray();
                    probs.addAll(list);
                    return probs;
                });

        CompletableFuture<JSONArray> drugs = pat_sum_uuid
                .thenCompose(uuid -> CassandraClient.DB.executeAsync("select * from drugs where mha_uid=? and inserted=?", user, uuid))
                .thenApply(rows -> {
                    //System.out.println("drugs " + Thread.currentThread().getName());
                    List<JSONObject> list = rows.all().stream()
                            .filter(row -> {
                                LocalDate start = row.getTimestamp("start_date") == null ? LocalDate.MIN : row.getTimestamp("start_date").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                                LocalDate end = row.getTimestamp("end_date") == null ? LocalDate.MAX : row.getTimestamp("end_date").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                                boolean no_overlap = end.isBefore(from) || start.isAfter(to);
                                return !no_overlap;
                            })
                            .map(row -> {
                                JSONObject drug = new JSONObject();
                                drug.put("atc_code", row.getString("atc_code"));
                                drug.put("title", row.getString("title"));

                                JSONObject dose = new JSONObject();
                                dose.put("value", row.getFloat("dose"));
                                dose.put("unit", row.getString("dose_unit"));
                                drug.put("dose", dose);

                                //Optional.of(row.getTimestamp("start_date")).map(d -> d.toInstant().toString()).orElse(null);
                                drug.put("start_date", row.getTimestamp("start_date") != null ? row.getTimestamp("start_date").toInstant().toString().substring(0, 10) : null);
                                drug.put("end_date", row.getTimestamp("end_date") != null ? row.getTimestamp("end_date").toInstant().toString().substring(0, 10) : null);
                                return drug;
                            }).collect(toList());
                    JSONArray probs = new JSONArray();
                    probs.addAll(list);
                    return probs;
                });
        CompletableFuture<JSONArray> vital_signs = pat_sum_uuid
                .thenCompose(uuid -> CassandraClient.DB.executeAsync("select * from vital_signs where mha_uid=? and inserted=?", user, uuid))
                .thenApply(rows -> {
                    //System.out.println("signs " + Thread.currentThread().getName());
                    List<JSONObject> list = rows.all().stream()
                            .filter(row -> {
                                LocalDate when = row.getTimestamp("happened").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                                boolean no_contains = when.isBefore(from) || when.isAfter(to);
                                return !no_contains;
                            })
                            .map(row -> {
                                JSONObject sign = new JSONObject();
                                sign.put("loinc_code", row.getString("loinc_code"));
                                sign.put("title", row.getString("title"));
                                sign.put("units", row.getString("units"));
                                sign.put("value", row.getFloat("value"));
                                String when = row.getTimestamp("happened").toInstant().toString();
                                sign.put("when", when.substring(0, 10));

                                return sign;
                            }).collect(toList());
                    JSONArray signs = new JSONArray();
                    signs.addAll(list);
                    return signs;
                });

        CompletableFuture<JSONArray> dcm_images =
                CassandraClient.DB.executeAsync("select when, inserted, series_uid, study_uid, study_description, modality, instance_uids from dcm_images where mha_uid=?", user)
                        .thenApplyAsync(rows -> {
                            List<JSONObject> list = rows.all().stream()
                                    .filter(row -> {
                                        LocalDate when = row.getTimestamp("when").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                                        boolean no_contains = when.isBefore(from) || when.isAfter(to);
                                        return !no_contains;
                                    })
                                    .map(row -> {
                                        JSONObject img = new JSONObject();
                                        img.put("when", row.getTimestamp("when").toInstant().toString().substring(0, 10));
                                        final String series_uid = row.getString("series_uid");
                                        img.put("series_uid", series_uid);
                                        img.put("study_uid", row.getString("study_uid"));
                                        img.put("study_description", row.getString("study_description"));
                                        img.put("modality", row.getString("modality"));
                                        final List<String> instance_uids = row.getList("instance_uids", String.class);
                                        img.put("instance_uids", instance_uids);
                                        img.put("count", instance_uids.size());
                                        final String selectInstance = instance_uids.get(instance_uids.size() / 2);
                                        img.put("icon", String.format("%s/wado?instance_uid=%s", baseURI, selectInstance));
                                        img.put("uri", String.format("%s/dcm?series_uid=%s", baseURI, series_uid));
                                        return img;
                                    })
                                    .collect(toList());
                            JSONArray images = new JSONArray();
                            images.addAll(list);
                            return images;

                        });

        CompletableFuture.allOf(problems, drugs, vital_signs, dcm_images)
                .whenComplete((v, ex) -> {
                    // System.out.println("all " + Thread.currentThread().getName());
                    if (ex != null) {
                        ex.printStackTrace();
                        if (exchange.getStatusCode() == StatusCodes.OK)
                            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                        exchange.getResponseSender().send(ex.getMessage());
                        exchange.endExchange();
                        return;
                    }
                    JSONArray probs = problems.join();
                    JSONArray drgs = drugs.join();
                    JSONArray signs = vital_signs.join();
                    JSONArray images = dcm_images.join();
                    JSONObject summary = new JSONObject();
                    summary.put("id", pat_sum_uuid.join().toString());

                    summary.put("active_problems", probs);
                    summary.put("drugs", drgs);
                    summary.put("vital_signs", signs);
                    JSONObject resObj = new JSONObject();
                    resObj.put("summary", summary);
                    resObj.put("medical_images", images);
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
                    final String jsonString = resObj.toJSONString();
                    exchange.getResponseSender().send(jsonString);
                    // System.out.println("Returned...");
                });

    }

    public static void store_images(final String user_uid, List<DICOMClient.Instance> images) {
        images.stream()
                .collect(Collectors.groupingBy(DICOMClient.Instance::getSeriesUID))
                .forEach((seriesUID, lst) -> {
                    final int index = lst.size() / 2;
                    final DICOMClient.Instance typicalInstance = lst.get(index);
                    Optional<File> iconFile = typicalInstance.createIconFile(200);
                    try {
                        ByteBuffer byteBuffer;
                        if (iconFile.isPresent())
                            byteBuffer = ByteBuffer.wrap(Files.readAllBytes(iconFile.get().toPath()));
                        else {
                            try (final InputStream defDicomImg = MHAClinicalAPI.class.getResourceAsStream("dicom.jpg")) {
                                final byte[] b = new byte[defDicomImg.available()];
                                new DataInputStream(defDicomImg).readFully(b);
                                byteBuffer = ByteBuffer.wrap(b);
                            }
                        }
                        final List<String> instanceUIDs = lst.stream().map(DICOMClient.Instance::getInstanceUID).collect(toList());
                        CassandraClient.DB.executeAsync("INSERT INTO dcm_images(mha_uid, inserted, when, series_uid, study_uid, study_description, modality, icon_jpg, instance_uids) VALUES(?,now(),?, ?,?,?,?,?,?)",
                                user_uid,
                                typicalInstance.getAcquisitionDate(),
                                seriesUID,
                                typicalInstance.getStudyUID(),
                                typicalInstance.getStudyDescription(),
                                typicalInstance.getModality(),
                                byteBuffer,
                                instanceUIDs);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
    }

    public static void chf_triplestore(SPARQLClient sc,
                                       final String drugsQuery,
                                       final String problemsQuery,
                                       final HttpServerExchange exchange) {

        Map<String, Deque<String>> params = exchange.getQueryParameters();
        final String user = params.containsKey("username") ? params.get("username").getFirst() : "";

        final LocalDate to = LocalDate.now(), from = to.minusMonths(18);

        // Get all the ICD-10 coded "problems":
        CompletableFuture<Set<String>> problems =
                sc.send_query_and_parse(problemsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> records.stream()
                                .filter(map -> (!"".equals(map.get("code_icd_10"))))
                                .map(map -> map.get("code_icd_10").toUpperCase())
                                .collect(Collectors.toSet()));
        // Get all the ATC codes for drugs
        CompletableFuture<Set<String>> drugs =
                sc.send_query_and_parse(drugsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> records.stream()
                                /*
                                .filter(row -> {
                                    LocalDate end = "".equals(row.get("end_date")) ? LocalDate.MAX : LocalDate.parse(row.get("end_date").substring(0, 10), DateTimeFormatter.ISO_LOCAL_DATE);
                                    return !end.isBefore(from);
                                })
                                */
                                .map(map -> map.get("atc_code").toUpperCase())
                                .collect(Collectors.toSet()));

        CompletableFuture.allOf(drugs, problems)
                .whenComplete((v, ex) -> {
                    if (ex != null) {
                        ex.printStackTrace();
                        if (exchange.getStatusCode() == StatusCodes.OK)
                            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                        exchange.getResponseSender().send(ex.getMessage());
                        exchange.endExchange();
                        return;
                    }
                    final Set<String> drgs = drugs.join();
                    final Set<String> probs = problems.join();

                    // Keep only the first 3 chars of the ICD10 code
                    final Set<String> probs_prefixes = probs.stream()
                            .map(p -> p.substring(0,3))
                            .collect(Collectors.toSet());

                    // See: https://en.wikipedia.org/wiki/Chronic_obstructive_pulmonary_disease
                    final boolean hasCOPD = Arrays.asList("J40", "J41", "J42", "J43", "J44", "J47")
                            .stream()
                            .anyMatch(probs_prefixes::contains);

                    // See https://en.wikipedia.org/wiki/Heart_failure
                    final boolean hadHF = probs_prefixes.contains("I50");

                    // See: https://en.wikipedia.org/wiki/Valvular_heart_disease
                    final boolean hasValveDisease = Arrays.asList("I05", "I06", "I07", "I08", "I34", "I35", "I36", "I37", "Q22", "Q23")
                            .stream()
                            .anyMatch(probs_prefixes::contains);

                    //See https://en.wikipedia.org/wiki/Beta_blocker
                    final boolean receivesBetaBlockers = drgs.stream().anyMatch(d -> d.startsWith("C07"));

                    //See https://en.wikipedia.org/wiki/ACE_inhibitor
                    final boolean receivesACEI = drgs.stream().anyMatch(d -> d.startsWith("C09"));

                    JSONObject resObj = new JSONObject();
                    resObj.put("drugs", drgs);
                    resObj.put("problems", probs);
                    resObj.put("valve_disease", hasValveDisease);
                    resObj.put("hf", hadHF);
                    resObj.put("copd", hasCOPD);
                    resObj.put("beta_blockers", receivesBetaBlockers);
                    resObj.put("acei", receivesACEI);
                    resObj.put("user", user);
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
                    final String jsonString = resObj.toJSONString();
                    exchange.getResponseSender().send(jsonString);
                });
    }

    public static CompletableFuture<Set<String>> dcmInstanceUidsOfUser(SPARQLClient sc, final String user,
                                                                  final String imagesQuery) {

        final LocalDate from = LocalDate.parse("1800-01-01", DateTimeFormatter.ISO_LOCAL_DATE);
        final LocalDate to = LocalDate.parse("9999-12-30", DateTimeFormatter.ISO_LOCAL_DATE);
        String q = imagesQuery.replace("{USER}", user)
                .replace("{START_DATE}", from.toString())
                .replace("{END_DATE}", to.toString());

        // System.out.println(q);
        return sc.send_query_and_parse(q)
                .thenApplyAsync(records -> {
                    Pattern pattern = Pattern.compile("'[\\d.]+'"); // Match an instance UID in single quotes
                    return records.stream()
                            .flatMap(map -> {
                                final String series_uid = map.get("series_uid");
                                final Matcher matcher = pattern.matcher(map.get("instance_uids"));
                                List<String> inst_uids = new ArrayList<>();
                                // Find all matches
                                while (matcher.find()) {
                                    // Get the matching string
                                    String match = matcher.group();
                                    inst_uids.add(match.substring(1, match.length() - 1));
                                }
                                return inst_uids.stream();
                            })
                            .collect(Collectors.toSet());
                });
    }

    public static CompletableFuture<Set<String>> dcmSeriesUidsOfUser(SPARQLClient sc, final String user,
                                                                     final String imagesQuery) {

        final LocalDate from = LocalDate.parse("1800-01-01", DateTimeFormatter.ISO_LOCAL_DATE);
        final LocalDate to = LocalDate.parse("9999-12-30", DateTimeFormatter.ISO_LOCAL_DATE);
        String q = imagesQuery.replace("{USER}", user)
                .replace("{START_DATE}", from.toString())
                .replace("{END_DATE}", to.toString());

        // System.out.println(q);
        return sc.send_query_and_parse(q)
                .thenApplyAsync(records -> records.stream()
                        .map(map -> map.get("series_uid"))
                        .collect(Collectors.toSet()));
    }

    public static void ask_triplestore(SPARQLClient sc, DICOMClient dc, final String user,
                                       final String imagesQuery,
                                       final String drugsQuery,
                                       final String vitalSignsQuery,
                                       final String problemsQuery,
                                       final String alertsQuery,
                                       final String baseURI, HttpServerExchange exchange) {

        Map<String, Deque<String>> params = exchange.getQueryParameters();
        final LocalDate from = LocalDate.parse(params.containsKey("from")
                ? params.get("from").getFirst()
                : "1800-01-01", DateTimeFormatter.ISO_LOCAL_DATE);
        final LocalDate to = LocalDate.parse(params.containsKey("to")
                ? params.get("to").getFirst()
                : "9999-12-30", DateTimeFormatter.ISO_LOCAL_DATE);

        String q = imagesQuery.replace("{USER}", user)
                .replace("{START_DATE}", from.toString())
                .replace("{END_DATE}", to.toString());
        // System.out.println(q);
        CompletableFuture<JSONArray> medical_images =
                sc.send_query_and_parse(q)
                        .thenApplyAsync(records -> {
                            Pattern pattern = Pattern.compile("'[\\d.]+'"); // Match an instance UID in single quotes
                            List<JSONObject> results = records.stream()
                                    .map(map -> {
                                        final String series_uid = map.get("series_uid");
                                        JSONObject img = new JSONObject();
                                        img.put("series_uid", series_uid);
                                        img.put("when", map.get("when"));
                                        img.put("study_uid", ""); // XXX
                                        img.put("study_description", map.get("study_description"));
                                        img.put("modality", map.get("modality"));
                                        final Matcher matcher = pattern.matcher(map.get("instance_uids"));
                                        List<String> inst_uids = new ArrayList<>();
                                        // Find all matches
                                        while (matcher.find()) {
                                            // Get the matching string
                                            String match = matcher.group();
                                            inst_uids.add(match.substring(1, match.length() - 1));
                                        }

                                        img.put("instance_uids", inst_uids);
                                        img.put("count", inst_uids.size());
                                        if (inst_uids.size() > 0) {
                                            final String selectInstance = inst_uids.get(inst_uids.size() / 2);
                                            img.put("icon", String.format("%s/wado?instance_uid=%s", baseURI, selectInstance));
                                            img.put("uri", String.format("%s/dcm?series_uid=%s", baseURI, series_uid));
                                        }
                                        return img;

                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });

        CompletableFuture<JSONArray> drugs =
                sc.send_query_and_parse(drugsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> {
                            List<JSONObject> results = records.stream()
                                    .filter(row -> {
                                        LocalDate start = "".equals(row.get("start_date")) ? LocalDate.MIN : LocalDate.parse(row.get("start_date").substring(0, 10), DateTimeFormatter.ISO_LOCAL_DATE);
                                        LocalDate end = "".equals(row.get("end_date")) ? LocalDate.MAX : LocalDate.parse(row.get("end_date").substring(0, 10), DateTimeFormatter.ISO_LOCAL_DATE);
                                        boolean no_overlap = end.isBefore(from) || start.isAfter(to);
                                        return !no_overlap;
                                    })
                                    .map(map -> {
                                        JSONObject obj = new JSONObject();
                                        obj.put("title", map.get("title"));
                                        obj.put("atc_code", map.get("atc_code"));
                                        obj.put("start_date", map.get("start_date").substring(0, 10));
                                        obj.put("end_date", map.get("end_date").substring(0, 10));
                                        JSONObject dose = new JSONObject();
                                        dose.put("unit", map.get("dose_unit"));
                                        dose.put("value", Float.parseFloat(map.getOrDefault("dose", "0.0")));
                                        obj.put("dose", dose);
                                        return obj;
                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });

        CompletableFuture<JSONArray> signs =
                sc.send_query_and_parse(vitalSignsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> {
                            List<JSONObject> results = records.stream()
                                    .filter(row -> {
                                        if ("".equals(row.get("inserted_date")))
                                            return true;
                                        LocalDate when = LocalDate.parse(row.get("inserted_date").substring(0, 10), DateTimeFormatter.ISO_LOCAL_DATE);
                                        return when.isBefore(to) && when.isAfter(from);
                                    })
                                    .map(map -> {
                                        JSONObject obj = new JSONObject();
                                        obj.put("title", map.get("title"));
                                        obj.put("loinc_code", map.getOrDefault("loinc_code", "").replace("http://purl.bioontology.org/ontology/LOINC/", ""));
                                        obj.put("when", "".equals(map.get("inserted_date")) ? null : map.get("inserted_date").substring(0, 10));
                                        obj.put("units", map.get("units"));
                                        obj.put("value", Float.parseFloat(map.getOrDefault("value", "0.0")));
                                        return obj;
                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });

        CompletableFuture<JSONArray> problems =
                sc.send_query_and_parse(problemsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> {
                            List<JSONObject> results = records.stream()
                                    .map(map -> {
                                        JSONObject obj = new JSONObject();
                                        obj.put("title", map.get("title"));
                                        if (!"".equals(map.get("code_snomed"))) {
                                            obj.put("code", map.get("code_snomed"));
                                            obj.put("code_system", "SNOMED-CT");
                                        } else {
                                            obj.put("code", map.get("code_icd_10"));
                                            obj.put("code_system", "ICD10");
                                        }
                                        return obj;
                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });
        CompletableFuture<JSONArray> alerts =
                sc.send_query_and_parse(alertsQuery.replace("{USER}", user))
                        .thenApplyAsync(records -> {
                            List<JSONObject> results = records.stream()
                                    .map(map -> {
                                        JSONObject obj = new JSONObject();
                                        obj.put("title", map.get("title"));
                                        obj.put("when", "".equals(map.get("date")) ? null : map.get("date").substring(0, 10));
                                        return obj;
                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });
        CompletableFuture.allOf(medical_images, drugs, signs, problems, alerts)
                .whenComplete((v, ex) -> {
                    if (ex != null) {
                        ex.printStackTrace();
                        if (exchange.getStatusCode() == StatusCodes.OK)
                            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                        exchange.getResponseSender().send(ex.getMessage());
                        exchange.endExchange();
                        return;
                    }
                    JSONArray probs = problems.join();
                    JSONArray drgs = drugs.join();
                    JSONArray vital_signs = signs.join();
                    JSONArray images = medical_images.join();
                    JSONArray alrts = alerts.join();
                    JSONObject summary = new JSONObject();
//                    summary.put("id", pat_sum_uuid.join().toString());

                    summary.put("active_problems", probs);
                    summary.put("drugs", drgs);
                    summary.put("vital_signs", vital_signs);
                    JSONObject resObj = new JSONObject();
                    resObj.put("summary", summary);
                    resObj.put("medical_images", images);
                    resObj.put("alerts", alrts);
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
                    final String jsonString = resObj.toJSONString();
                    exchange.getResponseSender().send(jsonString);
                });

    }

    public static void alerts_from_triplestore(SPARQLClient sc, final String user,
                                               final String alertsQuery,
                                               final HttpServerExchange exchange) {

        String q = alertsQuery.replace("{USER}", user);
        // System.out.println(q);
        CompletableFuture<JSONArray> alerts =
                sc.send_query_and_parse(q)
                        .thenApplyAsync(records -> {
                            List<JSONObject> results = records.stream()
                                    .map(map -> {
                                        JSONObject obj = new JSONObject();
                                        obj.put("title", map.get("title"));
                                        obj.put("when", "".equals(map.get("date")) ? null : map.get("date").substring(0, 10));
                                        return obj;
                                    }).collect(Collectors.toList());

                            JSONArray list = new JSONArray();
                            list.addAll(results);
                            return list;
                        });
        alerts.whenComplete((jsonArray, ex) -> {
            if (ex != null) {
                ex.printStackTrace();
                exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                exchange.getResponseSender().send(ex.getMessage());
                exchange.endExchange();
                return;
            }
            exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");

            JSONObject resObj = new JSONObject();
            resObj.put("alerts", jsonArray);
            final String jsonString = resObj.toJSONString();
            exchange.getResponseSender().send(jsonString);

        });
    }

    private static JSONArray listOfSeriesToJSON(String baseURI,
                                                List<DICOMClient.Series> series_list) {
        final List<JSONObject> results = series_list.stream()
                .filter(series -> !series.isNull())
                .map(series -> {
                    final String series_uid = series.seriesUID;
                    JSONObject img = new JSONObject();
                    img.put("series_uid", series_uid);
                    img.put("when", series.seriesDate != null ? series.seriesDate.toInstant().toString().substring(0, 10) : null);
                    img.put("study_uid", series.studyUID);
                    img.put("study_description", series.studyDescription);
                    img.put("modality", series.modality);
                    img.put("instance_uids", series.instanceUID);
                    img.put("count", series.instanceUID.size());
                    final String selectInstance = series.instanceUID.get(series.instanceUID.size() / 2);
                    img.put("icon", String.format("%s/wado?instance_uid=%s", baseURI, selectInstance));
                    img.put("uri", String.format("%s/dcm?series_uid=%s", baseURI, series_uid));
                    return img;
                }).collect(toList());
        JSONArray images = new JSONArray();
        images.addAll(results);
        return images;
    }

    private static void quickly_dispatch(final HttpServerExchange exchange, Runnable func) {
        exchange.dispatch(exchange.isInIoThread() ? SameThreadExecutor.INSTANCE : exchange.getIoThread(),
                func);
    }

    public static void main(String... args) {

        if (args.length == 0) {
            System.err.println("Usage:\n\t java MHAClinicalAPI <config.properties>\nwhere config.properties is a properties file..");
            System.exit(-1);
        }
        Configuration config = Configuration.create(args[0]);
        assert config != null;

        AsyncHttpClient asyncHttpClient = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()
                .setAllowPoolingConnections(true)
                .setExecutorService(Executors.newCachedThreadPool())
                // .setMaxConnectionsPerHost(100)
                .build());
        //System.err.println("Configuration:\n"+config);

        sparqlClient = new SPARQLClient(asyncHttpClient, config.getSparqlURL());

        dicomClient = new DICOMClient(asyncHttpClient);
        dicomClient.setHost(config.getDicomHost())
                .setPort(config.getDicomPort())
                .setMyAET(config.getDicomCallingAET())
                .setSrvAET(config.getDicomCalledAET())
                .setWadoUrl(config.getWadoUrl());

        if (!dicomClient.verifyServer()) {
            System.out.println("DICOM Server verification " + dicomClient + " failed in C-ECHO");
            return;
        }

        CassandraClient.DB.connect(config.getCassandraKeyspace(), config.getCassandraUser(), config.getCassandraPwd(), config.getCassandraHost());
        final String imagesQuery = readQueryFromFile("DICOM_Series.sparql");
        final String drugsQuery = readQueryFromFile("Drugs.sparql");
        final String vitalSignsQuery = readQueryFromFile("Vital_signs.sparql");
        final String problemsQuery = readQueryFromFile("Problems.sparql");
        final String alertsQuery = readQueryFromFile("Alerts.sparql");
        // String diary_query = readQueryFromFile("Diary.sparql");
//        System.out.println(imagesQuery);

        final int port = config.getPort();

        final String myURI = config.getMyURI();
        final String baseURI = myURI.endsWith("/") ? myURI.substring(0, myURI.length() - 1) : myURI;
        final String tempUploadDir = config.getTempUploadDir().endsWith(File.separator) ? config.getTempUploadDir() : config.getTempUploadDir() + File.separator;
        final String tempStoreDir = tempUploadDir + File.separator + "_store";

        final HttpHandler wadoProxyHandler = Handlers.proxyHandler(new SimpleProxyClientProvider(dicomClient.getWadoUrl()));

        final HandlerWrapper tokenValidator = new AccessTokenValidator(config.getAccessTokenValidatorURI());

        final RoutingHandler routes = routing()
                .get("/patsum", exchange -> {
                    final String user = exchange.getAttachment(AccessTokenValidator.MHA_ACCOUNT).getPrincipal().getName();
                    quickly_dispatch(exchange, () -> ask_triplestore(sparqlClient, dicomClient, user,
                            imagesQuery, drugsQuery, vitalSignsQuery, problemsQuery, alertsQuery,
                            baseURI, exchange));
                })

                .get("/alerts", exchange -> {
                    final String user = exchange.getAttachment(AccessTokenValidator.MHA_ACCOUNT).getPrincipal().getName();
                    quickly_dispatch(exchange, () -> alerts_from_triplestore(sparqlClient, user,
                            alertsQuery, exchange));
                })

                .get("/dcm", exchange -> { // Retrieve a whole series
                    final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters();
                    if (!queryParameters.containsKey("series_uid")) {
                        exchange.setStatusCode(StatusCodes.NOT_FOUND);
                        exchange.getResponseSender().send("You must specify the 'series_uid' query parameter");
                        return;
                    }
                    final String seriesUid = queryParameters.get("series_uid").getFirst();
                    final String user = exchange.getAttachment(AccessTokenValidator.MHA_ACCOUNT).getPrincipal().getName();
                    exchange.dispatch( () -> {
                        dcmSeriesUidsOfUser(sparqlClient, user, imagesQuery)
                                .thenAccept(seriesUids -> {
                                    if (seriesUids.contains(seriesUid))
                                        get_dcm_series(dicomClient, seriesUid, exchange);
                                    else {
                                        exchange.setStatusCode(StatusCodes.UNAUTHORIZED);
                                        exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                        exchange.getResponseSender().send("You are not authorized to get this series...");
                                        exchange.endExchange();
                                    }
                                })
                                .exceptionally(ex -> {
                                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                    exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                    exchange.getResponseSender().send(ex.getMessage());
                                    exchange.endExchange();
                                    return null;
                                });

                    });
                })

                .get("/wado",
                        exchange -> {
                            final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters();
                            if (!queryParameters.containsKey("instance_uid")) {
                                exchange.setStatusCode(StatusCodes.NOT_FOUND);
                                exchange.getResponseSender().send("You must specify the 'instance_uid' query parameter");
                                return;
                            }

                            final String user = exchange.getAttachment(AccessTokenValidator.MHA_ACCOUNT).getPrincipal().getName();

                            final String instance_uid = queryParameters.get("instance_uid").getFirst();
                            exchange.dispatch( () -> {
                                        dcmInstanceUidsOfUser(sparqlClient, user, imagesQuery)
                                                .thenAccept(instances -> {
                                                    if (instances.contains(instance_uid)) {

                                                        exchange.setQueryString(DICOMClient.build_wado_request_query(instance_uid));
                                                        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "image/jpeg");
                                                        exchange.getResponseHeaders().put(Headers.CACHE_CONTROL, "max-age=86400");
                                                        try {
                                                            wadoProxyHandler.handleRequest(exchange);
                                                        } catch (Exception e) {
                                                            e.printStackTrace();
                                                            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                                            exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                                            exchange.getResponseSender().send(e.getMessage());
                                                            exchange.endExchange();
                                                        }
                                                    }
                                                    else {
                                                        exchange.setStatusCode(StatusCodes.UNAUTHORIZED);
                                                        exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                                        exchange.getResponseSender().send("You are not authorized to get this series...");
                                                        exchange.endExchange();
                                                    }
                                                })
                                                .exceptionally(ex -> {
                                                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                                    exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                                    exchange.getResponseSender().send(ex.getMessage());
                                                    exchange.endExchange();
                                                    return null;
                                                });
                                    });
                        })
                .get("/series", exchange -> {
                    final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters();
                    if (!queryParameters.containsKey("series_uid")) {
                        exchange.setStatusCode(StatusCodes.NOT_FOUND);
                        exchange.getResponseSender().send("You must specify the 'series_uid' query parameter");
                        return;
                    }
                    final String seriesUid = queryParameters.get("series_uid").getFirst();
                    if ("".equals(seriesUid)) {
                        exchange.setStatusCode(StatusCodes.NOT_FOUND);
                        exchange.getResponseSender().send("You must specify a non-empty value for the 'id' query parameter");
                        return;
                    }
                    final String user = exchange.getAttachment(AccessTokenValidator.MHA_ACCOUNT).getPrincipal().getName();
                    exchange.dispatch( () -> {
                        dcmSeriesUidsOfUser(sparqlClient, user, imagesQuery)
                                .thenAccept(seriesUids -> {
                                    if (!seriesUids.contains(seriesUid)) {
                                        exchange.setStatusCode(StatusCodes.UNAUTHORIZED);
                                        exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                        exchange.getResponseSender().send("You are not authorized to get this series...");
                                        exchange.endExchange();
                                        return;
                                    }
                                    dicomClient.find_series_async(seriesUid)
                                            .thenAccept(series -> {
                                                System.out.println(String.format("<%s> Series %s, pat_id=%s, study=%s, modality=%s\n",
                                                        Thread.currentThread().getName(),
                                                        series.seriesUID, series.patientId, series.studyUID, series.modality));
                                                if (series.isNull()) {
                                                    exchange.setStatusCode(StatusCodes.NOT_FOUND);
                                                    exchange.getResponseSender().send(String.format("Series <%s> does not contain any instances!\n", seriesUid));
                                                    exchange.endExchange();
                                                    return;
                                                }
                                                JSONObject js = new JSONObject();
                                                js.put("series_uid", series.seriesUID);
                                                js.put("patient_uid", series.patientId);
                                                js.put("study_uid", series.studyUID);
                                                js.put("series_date", series.seriesDate);
                                                js.put("instance_uids", series.instanceUID.stream()
                                                        .map(instance_uid -> JSONNavi.newInstanceObject()
                                                                .set("instance_uid", instance_uid)
                                                                .set("href", baseURI + "/wado?instance_uid=" + instance_uid)
                                                                .getRoot())
                                                        .collect(toList()));

                                                exchange.setStatusCode(StatusCodes.OK);
                                                exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "application/json");
                                                exchange.getResponseSender().send(js.toJSONString());
                                                exchange.endExchange();
                                            })

                                            .exceptionally(ex -> {
                                                exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                                exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                                exchange.getResponseSender().send(ex.getMessage());
                                                exchange.endExchange();
                                                return null;
                                            });

                                })
                                .exceptionally(ex -> {
                                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                    exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                    exchange.getResponseSender().send(ex.getMessage());
                                    exchange.endExchange();
                                    return null;
                                });

                    });
                    /*
                    quickly_dispatch(exchange, () -> {
                        dicomClient.find_series_async(seriesUid)
                                .thenAccept(series -> {
                                    System.out.println(String.format("<%s> Series %s, pat_id=%s, study=%s, modality=%s\n",
                                            Thread.currentThread().getName(),
                                            series.seriesUID, series.patientId, series.studyUID, series.modality));
                                    if (series.isNull()) {
                                        exchange.setStatusCode(StatusCodes.NOT_FOUND);
                                        exchange.getResponseSender().send(String.format("Series <%s> does not contain any instances!\n", seriesUid));
                                        exchange.endExchange();
                                        return;
                                    }
                                    JSONObject js = new JSONObject();
                                    js.put("series_uid", series.seriesUID);
                                    js.put("patient_uid", series.patientId);
                                    js.put("study_uid", series.studyUID);
                                    js.put("series_date", series.seriesDate);
                                    js.put("instance_uids", series.instanceUID.stream()
                                            .map(instance_uid -> JSONNavi.newInstanceObject()
                                                    .set("instance_uid", instance_uid)
                                                    .set("href", baseURI + "/wado?instance_uid=" + instance_uid)
                                                    .getRoot())
                                            .collect(toList()));

                                    exchange.setStatusCode(StatusCodes.OK);
                                    exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "application/json");
                                    exchange.getResponseSender().send(js.toJSONString());
                                    exchange.endExchange();
                                })
                                .exceptionally(ex -> {
                                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                                    exchange.getResponseHeaders().put(new HttpString(HttpHeaders.CONTENT_TYPE), "text/plain");
                                    exchange.getResponseSender().send(ex.getMessage());
                                    exchange.endExchange();
                                    return null;
                                });
                    });
*/

                })

                .add("options", "/upload", exchange -> {
                    exchange.setStatusCode(StatusCodes.NO_CONTENT);
                    exchange.getResponseHeaders().put(new HttpString("Access-Control-Allow-Origin"), "*");
                    exchange.getResponseHeaders().put(new HttpString("Access-Control-Allow-Methods"), "POST, GET, OPTIONS");
                    exchange.endExchange();

                })
                .post("/upload", new UploadHandler(tempUploadDir, tempStoreDir));

        final HttpHandler chfHandler = exchange -> quickly_dispatch(exchange,
                () -> chf_triplestore(sparqlClient, drugsQuery, problemsQuery, exchange));

        final HttpHandler authenticatingHandler = tokenValidator.wrap(routes);

        HttpHandler rootHandler = new PredicateHandler(
                //XXX: The handler for the COPD is not secure, it is called via the portal API
                httpServerExchange -> httpServerExchange.getRequestPath().equals("/chf"), chfHandler,
                authenticatingHandler);

        if (config.getLogDirPath() != null) {
            final AccessLogHandler logHandler = new AccessLogHandler(rootHandler,
                    new DefaultAccessLogReceiver(Executors.newSingleThreadExecutor(),
                            config.getLogDirPath().toFile(),
                            "access_log."),
                    "combined",
                    MHAClinicalAPI.class.getClassLoader());
            rootHandler = logHandler;
            System.out.println("Logging available at " + config.getLogDirPath());
        }

        Undertow server = Undertow.builder()
                .addHttpListener(port, "0.0.0.0")
                .setHandler(rootHandler)
                .build();

        server.start();
        Runtime.getRuntime().addShutdownHook(new Thread(server::stop));
        System.out.printf("Server started, listening at %d\n", port);
    }

}

redpajama_set_name: RedPajamaGithub


This collection of coloring pages neyon cat is really cute cat coloring pages for your kids. You have permission to download without charge by clicking the DOWNLOAD button under the image. It will communicate with a new page. Do right click on the snapshot, then select save picture as… After that you have permission to revise the file name and the folder where you want to save the file. Then click the save button.
Check out these pictures related to coloring pages neyon cat, hope it is useful..


text:
INFORMS 2002
Some Aspects of Optimization Methods in Aircrew Scheduling
The University of Auckland, New Zealand
Besides constructing aircrew tours of duty or pairings with minimal cost, airlines also wish to construct pairings that are robust in that flight schedule disruptions are less likely to propagate delays into the future. In general a minimal cost solution is likely to lack robustness and conversely a solution with maximum robustness (however this might be measured) is likely to be more expensive. Professor Ryan will describe the aircrew scheduling process and in particular the pairings problem. He will review the development of optimization methods based on the set-partitioning model that produce minimal cost solutions. A measure of robustness for each pairing will then be developed and the concept of a linear robustness objective will be discussed. The two objectives of cost and robustness will be treated in a bi-criterion optimization to generate "efficient" pairings that do not allow a simultaneous improvement in cost and robustness. We show that treating the cost objective as a constraint while maximizing robustness leads to very difficult integer programming problems. This situation can be overcome by treating the cost objective as an elastic constraint and penalizing violations of the constraint in the robustness objective. (Some of this research is joint work with Matthias Ehrgott.)
David Ryan is Professor of Operations Research at the University of Auckland. Until the end of last year he was Head of the Department of Engineering Science. This year he has been on sabbatical in England, Denmark, Chile and the US. He is responsible for some fundamental and influential ideas in the field of applied combinatorial optimization, such as the set partitioning approach to routing and scheduling, and the constraint branching method for speeding up branch-andbound searches in certain applications. Professor Ryan's research has significantly influenced OR applications throughout the world, especially with regard to airline crew scheduling problems. His work in this application area resulted in Air New Zealand being selected as a finalist in the 2000 Edelman competition. Professor Ryan has a keen interest in the practical use of OR methods to solve real-world problems and he is an acknowledged master at inspiring students, colleagues and people in industry to practice OR to maximum advantage.

redpajama_set_name: RedPajamaCommonCrawl


Our spring and summers are filled with lots of outings and picnics, having three small children I am always on the go. Having a great snack bag, or picnic tote is a must. I found these great totes from Sachi to carry all of out goodies! Sachi totes are a fun and fresh designed insulated tote that is great to have for everyday life things like a picnic, school function, sporting event and more.
I love the sleek designs and variety Sachi offers. The front zipper pocket is great for things like my keys and cell phone, I don't want too much baggage when we are out so being able to fit everything in one bag is great. We have already taken our Sachi's on a few outings and picnics, they have been great to keep our lunch cool.
Along with the great totes they also carry wine totes, a Kora line of eco-friendly bags to replace your plastic and paper bags, Market totes, and Cool Gems. If you are looking for a great insulated tote this spring and summer you should check out Sachi!
*Limited to US residents 18 years old and above. Giveaway starts May 2 2013 and ends on May 16, 2013 at 12:01 am EST. Winner will be emailed and has 72 hours to respond before another winner is selected. I was not paid for this giveaway or post. The opinions on this item are 100% mine and may vary from others. The sponsor is responsible for providing the prize. I was sent a product to review for this post.
There are several I really like including 36-097 and also really like several of the others as well. Thank you for the chance to win one of these great totes!
I like the Faux Ostrich, Red.
I like the Style 154-184 Black Medallion print tote. Very nice.
I like 154-182. Thanks for a chance to win this wonderful giveaway!
I like the Trellis Basket set!
The bling bag in blue. The baskets are really nice also.
Love the Red Apple print!! That is so my style!
Love the Red Apple print!
I really like the Grey Plaid bag (Style 36-097).
The Utility Tote with Cooler set looks very nice!


text:
Q: CSS Form underline text field animation effect I have the following code (below) of my form section and in it i want this (below image) underline animation to be done in the text input field . Whenever the user focus on the field the animation to be done.
the animation is to be smooth ease.
But something is missing i can't find in it. What is wrong and How to fix it?
Anyone Please help

html {
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizelegibility;
}

html, body {
  height: 100%;
}
#contact {
  font-family: "Montserrat", sans-serif;
  font-size: 14px;
  font-weight: 300;
  letter-spacing: 3px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-flow: row wrap;
      flex-flow: row wrap;
  margin: 10% 0;
}
#contact main, body footer {
  width: 100%;
}
#contact main {
  height: 100%;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

.form .text-input, .form .textarea, .form .label, .form .button {
  padding: 1em 1.5em;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  outline: none;
  line-height: normal;
  border: 1px solid transparent;
  border-radius: 0;
}

.form .text-input, .form .textarea {
  font: inherit;
  line-height: normal;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding-left: 0;
  border-bottom-color: #00d2ff;
  background: transparent;
  outline: none;
  color: black;
}
.form .text-input:placeholder, .form .textarea:placeholder {
  color: rgba(0, 0, 0, 0.7);
}
.form .text-input:-webkit-autofill, .form .textarea:-webkit-autofill {
  box-shadow: 0 0 0px 1000px white inset;
  border-top-color: white;
  border-left-color: white;
  border-right-color: white;
}
.form .error.text-input, .form .error.textarea, .error .form .text-input, .form .error .text-input, .error .form .textarea, .form .error .textarea {
  border-color: transparent transparent red transparent;
}
.form:not(.has-floated-label) .text-input:active, .form:not(.has-floated-label) .textarea:active, .form:not(.has-floated-label) .text-input:focus, .form:not(.has-floated-label) .textarea:focus {
  border-color: transparent transparent black transparent;
}

.form .label {
  position: absolute;
  z-index: 10;
  pointer-events: none;
  padding-left: 0;
}

.form .label {
  top: 0;
  left: 0;
  color: rgba(0, 0, 0, 0.3);
  -webkit-transition: color 0.3s;
  transition: color 0.3s;
}
.active .form .label, .form .active .label {
  font-size: 0.80em;
  line-height: 1;
  font-weight: 600;
  text-transform: uppercase;
  padding: 0;
  color: rgba(0, 0, 0, 0.7);
  background: white;
}
.focus .form .label, .form .focus .label {
  color: black;
}

.form.has-floated-label .field:after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0%;
  border-bottom: 3px solid #00d2ff;
  -webkit-transition: width 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
  transition: width 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}

.form.has-floated-label .field.focus:after {
  width: 100%;
}

.form .button {
  font: inherit;
  line-height: normal;
  cursor: pointer;
  background-color: #00d2ff;
  color: white;
  text-transform: uppercase;
  text-align: center;
  letter-spacing: 0.14286em;
  transition-duration: 0.4s;
}
.form .button:hover, .form .button:focus, .form .button:active {
  box-shadow: 0 10px 15px rgba(0, 0, 0, .1);
}
.form .button:active {
  position: relative;
  top: 1px;
  left: 1px;
}

.form {
/*  max-width: 50em; */
  width: 100%;
  margin: 0 10%;
/*  padding: 1em 2em;  */
  box-sizing: border-box;
  overflow: hidden;
}
.form .field {
  position: relative;
  width: 100%;
  margin-bottom: 1.5em;
  float: left;

}
@media screen and (min-width: 40em) {
  .form .field.half {
    width: calc(50% - 2em);
    margin-right: 2em;
  }
  .form .field.half + .half {
    margin-left: 2em;
    margin-right: 0;
  }
}
.form .field:last-child {
  float: right;
  width: auto;
}
.form .textarea {
  max-width: 100%;
}

  <form action='' class='form'>

      Name
      <input class='text-input' id='name' name='name' required type='text'>

      E-mail
      <input class='text-input' id='email' name='email' required type='email'>

      Message
      <textarea class='textarea' cols='50' id='message' name='message' required rows='4'></textarea>

      <input class='button' type='submit' value='Send message'>

  </form>

A: This is an example:

.input-name{
  position: relative;
  display: inline-block;
  overflow: hidden;
}
.input-name > input[type=text]{
  border: none;
  border-bottom: 2px solid red;
  outline: none;
}

.underline-animation{
  transition: all 0.5s;
  display: inline-block;
  bottom: 0;
  left: -100%;
  position: absolute;
  width: 100%;
  height: 2px;
  background-color: #64e4fe;
}
.input-name > input[type=text]:focus + .underline-animation{
  left: 0;
}

  <input type="text" placeholder="name">

A: I don't think this is possible with only the underline element since I know of no way to animate it like that, you can use the
 element though.
then you can do
hr{
    position:relative;
    left:0;
    width:0%;
    height:2px;
    background-color:#1784E1;
    border:none;
    margin-top:0;
    margin-left:0;
    margin-bottom:20px;
    transition:0.5s;
}
input:focus + hr{
    width:100%;
}

if you go to sam.apostel.be/TAD, is that what you want?

redpajama_set_name: RedPajamaStackExchange


text:
Noni Madueki discusses 'similarities' to the Chelsea legend
New Chelsea signing Noni Madueki has named Eden Hazard as his favorite Blues player from the past upon completing his move from PSV Eindhoven.
Madueki never played professionally in his native England, but was born in London, and moved to PSV Eindhoven when he was 16 after stints in the academies at both Crystal Palace and Tottenham.
The 20-year-old is another key addition to Chelsea's long-term recruitment target, dubbed 'Vision 2030They continue to mobilize as many young talents as possible in hopes of developing them into future superstars.
Madueke is left-footed but plays right-footed.
"I started as a central midfielder and then moved to the right wing, maybe when I was 16 or 17," the player told the club's media in his first interview as a Chelsea player.
I like to get the ball and be sexy, play with the players, beat the players, create a lot and score goals.
He was asked about his prominent ex-name Chelsea Player, Madueke finds Hazard due to the type of player he has been with the club and the "similarities" to his game.
He said: "Maybe I should say Eden Hazard…just to take you off your seat type of player".
"Very exciting in terms of the glow to get people off their seats and the creativity. There are similarities in Defo, but I hope to be as good as him one day."
Listen now to Son of Chelsea, part of the Network's 90-Minute Podcast, as Daniel Childs reacts to Chelsea's potential unwanted player signings, Levi Colwill's new contract, and more information on Mykhailo Mudryk's transfer and midfield plans for January . If you don't see this embed, click here To listen to the podcast!
Sporting Lisbon boss joins Pedro Buru as Tottenham talks continue
The Warriors nail Steve Kerr's blueprint in a much-needed win over the Raptors
Previous: Musk testifies in a fraud trial, stating that not everyone believes what he says
Next: T-Mobile's latest data breach affects 37 million customers
This 403-page Dungeons & Dragons game system is now licensed under Creative Commons • TechCrunch
First example of a classical quasiparticle, reveals deep connections between classical and quantum dissipation systems – ScienceDaily
This weekend's best tablet deals: Kindle, Microsoft Surface Pro, and more are on sale starting January 28th


text:
Aston Martin DBX () — кросовер від компанії Aston Martin.

Опис

Для моделі наданий турбомотор V8 4.0 (550 к.с., 700 Нм) з дев'ятиступеневою АКПП 9G-Tronic виробництва Mercedes-AMG. Повний привід 4Matic з раздаткою і муфтою для підключення передніх коліс, а також регульований в діапазоні 50 мм кліренс. Глибина подоланого броду 500 мм, кути в'їзду і з'їзду до 25,7° і 27,1° відповідно. Багажник (632 л + 62 л в підпіллі).
Розгін від 0 до 100 км/год займає 4,5 с, максимальна швидкість становить 291 км/год.

Спереду встановлені шини Pirelli P Zero розмірністю 285/40 R22, а ззаду 325/35 R22.

Інтер'єр DBX включає мікс з натуральної шкіри, алькантари, горіхового шпону і ворсистих килимів. Уже «в базі» автомобіль укомплектований: трьохзонним клімат-контролем, підігрівом всіх сидінь, панорамою, 12,3-дюймової цифровий приборки і запозиченим у концерну Daimler мультимедійним комплексом, що включає екран діагоналлю 10,25-дюймів і центральний тачпад.

Світова прем'єра кросовера пройшла в 20 листопада 2019 року в Пекіні. Вже наступного року моделі додали першу спеціальну модифікацію Bowmore Edition, що виходить лімітованою кількістю 18 одиниць.

DBX707

1 лютого 2022 року компанія Aston Martin представила найпотужніший на момент виходу бензиновий кросовер в світі, який називається Aston Martin DBX707. Його двигун від Mercedes-AMG, був дещо доопрацьований фахівцями з Aston Martin, в результаті чого його потужність складає 707 к.с. та 900 Нм крутного моменту. Коробка передач MCT 9G-Tronic від AMG теж була покращена і отримала "мокре зчеплення" та змінені передавальні числа. У сумі всі модифікації  дозволяють спорт-кросоверу набирати першу сотню за 3.3 секунди та розганятись до максимальної швидкості в 310 км/год. Також зміни доторкнулись підвіски та рульового керування — вони стали більш спортивними. У задній частині автомобіля  встановлено карбонові спойлер та сплітер, а також чотирьохствольну вихлопну систему. Гальмівна система — покращена, карбон-керамічна, задні гальмівні диски — по 390 мм, передні — по 420 . В базі автомобіль оснащено 22-дюйовими дисками, проте за доплату, можливий 23-дюймовий варіант. Ціна на базову версію стартує з 232 тисяч доларів.

Coupe
В другій половині 2022 року дебютує версія DBX Coupe.

Двигуни
3.0 л M 256 E30 DEH LA G І6 435 к.с. при 5900–6100 об/хв, 520 Нм при 1800–5500 об/хв (DBX Straight Six для Китаю)
4.0 л M 177 DE 40 AL V8 550 к.с. при 6500 об/хв, 700 Нм при 2200–5000 об/хв
4.0 л M 177 DE 40 AL V8 707 к.с. при 6000 об/хв, 900 Нм при 2600–4500об/хв (DBX707)

Примітки

Посилання

Автомобілі Aston Martin
Автомобілі 2010-х

redpajama_set_name: RedPajamaWikipedia


There were over 3,500 authorized wiretaps in the U.S. last year, mostly related to drug cases. One state, however, has far more wiretaps than any other based on its population.
That state is ... Nevada. Data from the Administrative Office of U.S. Courts shows that the state had 38.2 wiretaps per 500,000 residents. That's quite a bit considering Colorado came in second-place with 12.4!
The figure is probably so high because Nevada has a lot of visitors every year, but its resident population is small at under 3 million people. And it's not surprising that most of the Nevada wiretaps took place near Las Vegas in Clark County.
The government isn't the only one that could be listening in. Find out who else could be spying on your phone.
California and New York were the only other states with over 10 wiretaps per 500,000 residents. California also led the nation in total wiretaps because of its large population.
On the other end of the spectrum, Hawaii, Montana, North Dakota, South Dakota and Vermont had no wiretap requests last year. So if you don't want the government listening in, it might be time to move.
The report highlights the trend away from landlines in this country. Almost all of the wiretaps took place on cellphones and other mobile gadgets.


text:
San Antonio College Removes Mascot That Represented 'Oppressive Force'
San Antonio College has decided to remove its 'Ranger' mascot after campus groups campaigned for its removal for more than a year.
Dr. Robert Vela
Advocates for the removal of the mascot said it represented the Texas Rangers who have brutalized Mexican Americans, Native Americans and members of the Black community.
"For generations, the Rangers were an oppressive force that used violence against Mexicans, Mexican Americans, African Americans, and Native Americans. Much of this history is only now emerging causing a reexamination of the Rangers," said a statement by the college.
The decision to be rid of the 'Ranger' mascot was made during a special session Tuesday of the College Council, a group consisting of college administrators, department directors, faculty chairs and program coordinators.
"This is a historic day!" said college president Dr. Robert Vela. "The debate is over and San Antonio College has gone on record as being inclusive, diverse, empowered, decisive, true to its values – and committed to doing the right thing. We've taken a great leap forward and now we can begin the process of fashioning a new mascot identity that reflects the very best qualities of our SAC community."
Bethune-Cookman University Football Players Sign Petition to Reinstate Ed Reed as Head Coach
Ed Reed Set to Become Head Football Coach for Bethune-Cookman University
Massachusetts Gov. Charlie Baker Selected President of the NCAA
Durant Family Foundation Commits $500,000 to Bowie State University for Basketball Arena Renovations


text:
Expanding The Audience
By Baldev Duggal
Published in Visioneers Gallery
In an era when the resolution of smartphone cameras has reached an astonishing 41 megapixels, and photo filter apps can render even the most mundane moment into a Technicolor feast for the eyes, digital photography may seem to be reaching a saturation point. Surprisingly, however, as digital imagery pervades all aspects of our lives, the reverence for photography in the art world has risen to new levels as proven in the sale of a fine-art photograph by Andreas Gursky auctioned for $4.5 million at Christie's, the highest price ever paid for a contemporary photographic piece. The long-standing dialogue on whether photography is art has now shifted to how digital photography is giving birth to a new genre of contemporary art, and challenging the way we see and shape the world around us. Painter Francis Bacon said, "I have looked at far more photographs than I have paintings. Because their reality is stronger than reality itself." No matter how ubiquitous it becomes, photography will continue to reconnect us to the familiar in new ways, and for that reason, photography will continue to challenge our notions of how to value it. As our minds become saturated with photos, our visual sensibilities become more discerning.
Art galleries and museums around the world have begun to offer audiences a wide range of curatorial experiences of photography. The more rarified the art, the more exclusive the venue for exhibiting the work. However, the inherent democracy of taking a photograph can truly only flourish in the public domain where it invokes a dialogue and reflection among the masses. Considering the exponentially growing base of photographers around the world with their state-of-the-art DSLRs, there needs to be far more venues for showing photography than what's being provided by galleries and museum exhibitions today. This juncture of prolific photography demands powerful curators who help us connect millions of single photos into cohesive thematic narratives.
United Photo Industries (UPI), a Brooklyn-based photography cooperative we work with, has developed a novel curatorial platform for bringing photography from around the world to the public domain. Their mission is to promote and showcase emerging photographers through curated exhibitions around the world. In partnership with media partners and local galleries, they produce site-specific installations that explore thematic directions in photography and bring the works of hundreds of fine-art photographers into public art installations.
Their iconic public installation titled THE FENCE is a summer-long outdoor photographic exhibition that explores the essence of community across cultural boundaries and geographical lines. THE FENCE is a site-specific exhibition presenting the work of 40 photographers on weather-proof photographic mesh, printed at Duggal, that stretched over 1,000 feet in length. Installed each summer along the Greenway in Brooklyn Bridge Park, THE FENCE launched in summer 2012 and reached an audience of more than one million visitors in its very first year. Showcasing at least six images from each participating photographer from a specified series and topic, UPI displays the photographs at a size of approximately three feet in height so that any individual even walking by the images can come in close contact with the detail and message of the photographs. Sam Barzilay, the creative director and founder of UPI, states the ambitious goals of the agency—"to promote appreciation of photography, visual storytelling and, above all, greatly expanding photography's audience by breaking out of the constraints of traditional spaces and re-contextualizing the use of photography in the public domain, which until now has been primarily the domain of the advertising world."
With a passion for bringing photography to the masses, Barzilay, along with Executive Producer Laura Roumanos and Creative Producer Dave Shelley, also created Photoville, a temporary photographic village set up with shipping containers in the heart of Brooklyn Bridge Park on the Brooklyn Waterfront. Celebrating photography in all its forms and across all levels, Photoville brings together a mix of exhibitions, lectures and workshops on photography, all against a milieu of an unprecedented summer celebration in New York.
United Photo Industries' team is constantly in search of photographers from around the world. In a year, they've put together 11 individual exhibitions. They even install photographs on East River Ferry boats and continue to do numerous photo fence installations around New York. Barzilay explains, "We feel we have found a unique avenue to contribute to the evolution of digital photography by taking it to the streets. Our numerous outdoor installations are providing interactions between photographers and viewers. We are able to reach hundreds of thousands of people, many of them having never stepped into a gallery before. Experienced in this unexpected context, stories and images presented by photographers are having a deeper impact and resonating with viewers." Extending their photography efforts toward educational outreach and support in the Brooklyn community, UPI is also involved with The Red Hook Justice Program, the Kurt Hahn School and a new initiative in Brownsville. "We are very proud to assist these young artists in finding their vision and voice through conversations with professional photographers and editors, active workshops and exhibitions at our gallery."
United Photo Industries has come to play an unprecedented role in the photography industry today. Just as photographers are hungry for venues to show their work and the public is equally eager to connect with images in a meaningful way, UPI has created a platform that educates and entertains, and provides a nexus for photography conversation and contemplation that had not existed in the public domain other than at museums that aren't as accessible to many people. As they expand their installations from the boroughs of New York to Boston and other cities, there's no doubt that UPI's role as photo ambassadors will delight audiences by bringing uniquely curated contemporary photography to people who are starting to discover the beauty and magnitude of the photography world.
We at Duggal are delighted to have entered into an ongoing partnership with the United Photo Industries to contribute to the evolution of digital photography by taking it to the streets around the world. I'm happy to support UPI's larger-than-life vision for democratizing photography. It's to my great pride that Creative Producer Dave Shelley states, "None of our large outdoor installations would be possible without the support of Duggal. We are very fortunate to have the right partner from the start. Their technical expertise has allowed us to streamline and realize our vision. We have worked together over the last two years and have produced amazing results together. Through all of our exhibitions and installation experiences, and with Duggal's input, we have been able to tweak the manufacturing process. Exploring new materials, quality of prints and production process, Duggal has helped to lead the way."


As if EDAC wasn't awesome enough, the Franklin Street Events Association is now gearing up to do the same thing EVERY SATURDAY in Summer. It will be a farmer's market with all locally grown produce, planning to accept EBT/SNAP so that everyone can have access to good food, and in addition it will include several artist and crafter booths! In short, Franklin Street is establishing its very own weekly Bazaar that will have wonderful fresh food, local art, and crafts all summer long. It's an amazing initiative and an local event not to be missed!


text:
Q: Syncing Firefox passwords between 2 computers - FF >= 57 I am using Firefox Quantum (v60).
I have some passwords stored in my current profile (#1).
I am also using FF in another computer (#2), with other passwords.
I mean to merge the two password lists into my current pc/profile (#1).
From what I found on the web, one could use FF sync.
Is there any way of doing the merge locally? (i.e., without sending my info to a third party)
The closest I could get is using PasswordFox (thanks Nir Sofer once again!) to reveal the passwords from one installation, and copy-paste one at a time. This avoids typing them, but it is still quite cumbersome.
PS: I do not want to export-import (#2 -> #1), I already know how to do that. I mean to merge passwords.
Related info:
https://support.mozilla.org/en-US/questions/959278
https://support.mozilla.org/en-US/questions/1143122


water jet cutting comes with a unique procedure that offers the best cut edge as well as getting rid of the necessity for second finishing processes. The waterjet cutting machine offers a lot of advantages like precision, flexibility, speed which are advantages that you usually will not achieve when using other metal fabrication procedures.
Today a lot of people have come to understand the beauty of using water jet cutting machines and now they are hiring water jet cutting services for their project. However, numerous companies are now offering such services and it is essential that you take time to evaluate the history and strengths of service provider. You will come across a broad assortment of options and you will need as well to find a partner that will bring quality to your project and also in an affordable and timely manner. Here is a simple roadmap to assist you to find the right water jet cutting services for your project.
One vital aspect to look at when choosing water jet cutting is the competence or the capabilities of the company you hire as you want a service provider that will have services that can actually cover the assignment that you need to be completed. The market will offer numerous water jet cutting firms that will be decent, but your project may have a particular need that not all firms that can offer-hence you should be keen on finding out whether the firm can deliver. It will be a costly inconvenient if hire a water jet cutting firm that will not have the capacity to handle your project in the best manner, later own leaving it halfway or causing serious delays.
Moreover, make sure that you are hiring a corporation or service provider who holds reputation for quality water jet cutting services. A firm will need offer topnotch services to gain good reputation and this will come after a lot of hard work and dedication, and such a firm will not put their reputation on the line by giving poor services. Take time and search for online reviews of the firms they will help you determining whether it is decent or not. However, some site will offer biased and fabricated reviews, so be careful when visiting sites for reviews go for credible websites.
Even though price needs not to be the sole aspect to look at when choosing the right water jet cutting service, it is a crucial aspect that you definitely need to pay attention to alongside other factors. As much as you would want to work with a company that will work within your spending plan, concentrating more on price will hurt other factors for instance, quality may suffer.


I get more queries about house plant cultivation than any other type of gardening. In fact, house plants are not difficult, providing you understand a few simple points.
House plants are not a special plant family. They are generally plants that cannot withstand cold temperatures, so in a cooler climate, they must be grown indoors. They must, however, be given conditions as near to those where they grow in the wild, and are not primarily inanimate ornaments.
No houseplant will survive indefinitely in a dark corner; many cannot stand hot, dry, stuffy rooms, and most will be killed in a short time if they are overwatered, although many can be revived if they have become short of water. Light levels are always lower indoors than outside, so give your houseplant the lightest spot you can find, although many will not take to direct south or west sun in summer; if this is the case, move them out of the sun until the autumn.
Buy a good house plant book, preferably one that gives the country of origin and describes the conditions where the plant can be found in its native environment. Once you have bought your plant, find the position in your home that matches these conditions as nearly as possible. This will help your purchase to re-establish as quickly as it can. Always buy from a reputable source - generally this is not a garage forecourt or a dark shelf in an ironmonger's shop.
Some garden centres have better facilities for displaying house plants than others - ideally they should have areas with differing temperatures and light levels where the plants will be reasonably happy until they are sold.
Check that the compost is not bone dry or soggy, and that smaller plants do not need immediate repotting. If the plants have clear plastic sleeves, try to inspect all the foliage, which can soon rot if bunched too tightly together. Never buy a plant which is not at its best; yellow, brown or falling leaves can indicate this.
Repotting is not a routine job for many house plants, and many will survive for some time completely pot bound if they are well fed and watered.
Resist the temptation to repot a brand new acquisition; let it settle down for a few weeks first. The obvious indication that a plant needs repotting is when the new growth starts to become stunted. Repotting should only take place in spring and early summer so the roots have a chance to become re-established before winter. Choose a pot no more than one or two sizes larger so there are no large pockets of compost which can become sour before the roots grow into them. A multi-purpose compost is suitable for smaller specimens, although a soil based John Innes type is better for large plants which may only need further repotting after several years.
A newly repotted flowering plant will start making fresh foliage first, and can stop flowering until the roots have reached the sides of the pot again. For this reason, it is best only to repot flowering houseplants when they stop flowering even when regularly fed.
Late winter is the time of year to begin feeding again after the winter rest. Any liquid or soluble plant food is better than none at all, but a balanced feed (such as Baby Bio) is more suited to foliage house plants, while flowering ones will perform better with a high potash feed such as Phostrogen or a specific tomato fertilizer.
If you have a cool room, or even better, a conservatory, bring some colour into your life at the end of winter by growing some flowering house plants. Those that should keep flowering for several weeks include indoor cyclamen, cineraria, jasmine, chrysanthemum, indoor azalea, and, if you really want to treat yourself, orchids. All these last longest if given a position at this time of year in full light; you should pick off dead flowers regularly and keep the compost moist but not wet, the exception being the azalea, which likes to be grown in very damp compost. Feed weekly with a flowering houseplant food to prolong the display.
Spring bulbs are an inexpensive, colourful and often fragrant way to cheer up a winter and early spring home. If you potted your own last autumn, check them every few days to see if they are ready to bring into the light. With hyacinths this is when there is about 3-4cm of growth and the flower bud is well developed; narcissi and tulips should be about 6-8 cm tall. Place in a cool, shady place until the shoots have started to turn green, when they can be placed in a light window to flower. Do not let them get too warm or the growth will be straggly and the flowers soon fade.
If you did not manage to pot up your own, garden centres will have a good selection now. Keep well watered and feed regularly with a general liquid houseplant feed, and remove dead flower heads. When all flowers have faded, move the pots into a cold, light place such as a garden shed or garage window, and continue to feed and water until the temperature outdoors has warmed up sufficiently to move them outside, usually sometime during March. When the leaves have started to turn yellow, the bulbs can be planted in the garden to naturalise.
During winter and early spring, your permanent houseplants may start to appear rather tired. A little attention will make them look altogether different, and the plants will benefit greatly from some loving care. Remove dead and dying leaves, pick fallen leaves off the top of the compost, trim off dead shoots and wipe the leaves over with a damp sponge to remove dust and restore the shine on leathery foliage. Plants with large, smooth leaves, like aspidistra, Swiss cheese plant and rubber plant, can be sprayed or wiped over with a leaf shine liquid for even better effect.
Check for pests and diseases, which can remain active throughout the winter on indoor plants. Spray with an insecticide and/or fungicide if necessary – hard to control pests like woolly aphid, mealy bug and scale insects are best dealt with by watering the compost with Vine Weevil Killer, which makes the foliage poisonous to pests and has a residual effect of 3-6 months. Do not be tempted to repot at this time of year, even if a plant looks pot bound.


We have found most of our customers don't really understand what is involved in diagnosing a problem with a car. One of the questions we hear a lot is, "Can't you just hook the computer up and it tells you what's wrong?" The answer to that is, "Not exactly." Diagnosing car problems is not entirely unlike what a doctor goes through diagnosing a health problem. There are steps we need to take in order to get it right.
Diagnostic computers are the number one misunderstood tool by people not familiar with using them in detail. A diagnostic computer does not tell us what is wrong with the car. Instead, the diagnostic computer gives us a voice to tell us about the problem and help us learn what the cause is.
When your check engine light comes on, we get one or more diagnostic codes. These are 5 digit codes that basically describe a symptom or problem the car is having. These are a starting point, much like telling a doctor "My knee hurts." The car equivalent may be "Misfire Cylinder 3." We know what the car is experiencing, but not what the cause is.
The next thing the computer tells us is what we call "freeze frame data." This is a snapshot of all the sensor and everything that was going on at the time the code was set. Back to our knee example, this answers the question, "What were you doing when the pain started?" Our experienced technicians can use this data to help figure out what may have happened to cause the problem.
Our high-end computer equipment will allow us to have tools sort of like an EKG, CAT-Scan, and other tools that doctors have. We can monitor live data from every sensor on the car and watch for anything out of the ordinary. We can also test individual components and run various tests by making a change and watching the computer data to see the result. All of these can help us narrow down the source of the problem.
Sometimes, the computer tools can get us right to the exact problem. Sometimes, we need a little more hands-on when the computer can't give us enough information. Like a doctor, we can do a visual inspection to look for anything abnormal or obvious damage. We may have to take things apart and inspect and test individual components like a doctor would do during exploratory surgery. Just like a doctor may not have to send every cough to get an MRI, we don't necessarily need to spend 15 hours of in-depth diagnostic time to get to the bottom of the issue. Most of the time, we can get enough information to find the problem with just a few steps.
As you can imagine, sometimes we need to spend a significant amount of time with your vehicle. We may need to subject it to various different conditions, such as driving cold, driving hot, highway and in-town driving, etc. in order to gather the information we need. You can help us by giving as many details as you can about what you are experiencing, when and how it happened, and what we can do to duplicate the issue. This will help us make sure we are testing just what we need to.
What am I actually paying for?
You don't need to know the water pump from the ignition coil in order to help us out. Here are a few things we wish every customer did.